home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Tools (InfoMagic)
/
Internet Tools.iso
/
news
/
readers
/
nnmvs
/
distrib.cntl.v3r1.Z
/
distrib.cntl.v3r1
Wrap
Text File
|
1995-04-24
|
1MB
|
30,015 lines
//JOBNAME JOB ACCOUNT,'NAME'
//*------------------------------------------------------------------*/
//* */
//* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
//* */
//* This software is provided on an "AS IS" basis. All warranties, */
//* including the implied warranties of merchantability and fitness, */
//* are expressly denied. */
//* */
//* Provided this copyright notice is included, this software may */
//* be freely distributed and not offered for sale. */
//* */
//* Changes or modifications may be made and used only by the maker */
//* of same, and not further distributed. Such modifications should */
//* be mailed to the author for consideration for addition to the */
//* software and incorporation in subsequent releases. */
//* */
//*------------------------------------------------------------------*/
//*
//* NNMVS - NNTP Client News Reader for MVS/ISPF - Version 3 Release 1
//*
//* Author: Steve Bacher <seb1525@mvs.draper.com>
//*
//* Date: March, 1993
//*
//*--------------------------------------------------------------------
//*
//* This job creates the NNMVS distribution libraries (PDS's).
//*
//* Run this JCL to create the PDS's, after customizing to suit.
//* (Obviously, put in a good JOB statement first.)
//* To customize the JCL, change the defaults on the //NNLOAD PROC
//* statement to your liking, particularly the PREFIX default.
//* You might also want to change the final qualifiers of the PDS's
//* created - to do this, find the // EXEC NNLOAD statements and
//* change the value of the TO parameter.
//*
//* See the $$README file (of the CNTL PDS, first in this stream)
//* for the rest of the installation instructions.
//*
//NNLOAD PROC CLS='*',BS='6160',U='3380',V='',
// TRK1='30',TRK2='10',DIR='35',RLSE='RLSE',
// PREFIX='NNMVS.INSTALL.'
//*
//IEBUPDTE EXEC PGM=IEBUPDTE,PARM=NEW
//SYSPRINT DD SYSOUT=&CLS
//SYSUT2 DD DISP=(NEW,CATLG,DELETE),DSN=&PREFIX.&TO,
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=&BS),
// SPACE=(TRK,(&TRK1,&TRK2,&DIR),&RLSE),UNIT=&U,VOL=SER=&V
//*
// PEND
//CNTL EXEC NNLOAD,TRK1='5',TO='CNTL'
//SYSIN DD DATA,DLM='?!'
./ ADD NAME=$$README,SSI=012C0002
------------------------------------------------------------------------
Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992
SAS enhancements copyright (c) 1992 SAS Institute, Inc.
This software is provided on an "AS IS" basis. All warranties,
including the implied warranties of merchantability and fitness,
are expressly denied.
Provided this copyright notice is included, this software may
be freely distributed and not offered for sale.
Changes or modifications may be made and used only by the maker
of same, and not further distributed. Such modifications should
be mailed to the author for consideration for addition to the
software and incorporation in subsequent releases.
------------------------------------------------------------------------
MVS NNTP News Reader - Version 3 Release 1
Author: Steve Bacher <seb1525@mvs.draper.com>
Enhancements by: Dale Ingold <snoddi@mvs.sas.com>
------------------------------------------------------------------------
New Features and Changes in member $CHANGES of the distribution.
------------------------------------------------------------------------
Contents of PDS's belonging to NNMVS distribution:
Member PDS Type Description
$$README CNTL This file
$CHANGES CNTL New features and changes
$MISC CNTL Miscellaneous gotchas and installation notes
ALLOAD CNTL JCL to allocate NNMVS load library
AUTH CNTL Sample server authorization file
COMPILE CNTL JCL to compile and link C source
GRAMMAR CNTL Description of NNMVS batch expression syntax
HELP CNTL Description of NNMVS batch language
NNMVS CNTL JCL to run NNMVS in batch
NNMVSHLP CNTL TSO HELP for the NNMVSP version of the exec
NNMFIUCV CLIST Exec to check for multiple socket applications
NNMVS CLIST Exec by which users invoke the news reader
NNMVSC CLIST CLIST by which users invoke the news reader
NNMVSL CLIST CLIST to run multiple-news-server ISPF dialog
NNMVSP CLIST Exec using XPROC to parse CLIST-style parms
NNMMAIL CLIST Exec called by news reader to send mail
NNM... PANEL ISPF regular panels
TNNM... PANEL ISPF tutorial panels
NN... H C headers for compilation
NNM... C C source for compilation
--------------------------------------------------------------------
Directions:
Assuming the PDS's have been created:
1. Customize the ALLOAD and COMPILE JCL members to reflect your
local conventions. Note: If you intend to place the executable into
an existing library, you can suppress that part of the ALLOAD JCL.
The name of the data set created must match across both members.
2. Customize the NNUSER header file as shown by the comments therein.
Note in particular the defines for your TCP/IP and your C compiler.
There are changes to the linkedit JCL that are related to these.
3. Choose which exec you want to use:
NNMVS - the traditional REXX exec, not much parameter passing
NNMVSP - REXX exec that uses XPROC to parse CLIST-style parms
NNMVSC - CLIST that accepts CLIST-style parameters
If you don't have XPROC (the utility that allows a REXX exec to parse
CLIST-style parameters), you can get it from the same place that you
got NNMVS. I highly recommend that you do so if you do a lot of
conversion from CLIST to REXX.
If you really can't or won't get XPROC, you can use the CLIST, but
keep in mind that there are some things the CLIST just can't do that
the REXX exec can. Refer to the comments therein for more details.
Customize whichever of the above you pick to define the names of the
MVS libraries to contain the panel and load library members. The load
library must be the one specified in the ALLOAD JCL, if you are
creating it anew. Observe the comments relating to the use of LIBDEF
and ISPF APPLIDs.
Note that if you install one of the REXX execs, you must also install
the NNMFIUCV exec in the same library. This exec implements a crude
check for an existing TCP/IP socket application (e.g. another NNMVS)
in a different PIE MultiTSO session. It prevents your users from
crashing TCP/IP, so it is highly recommended that you make use of it.
4. Customize the NNMMAIL exec to invoke your local mailer, or
otherwise insure that messages sent via MAIL or REPLY arrive at their
intended destination.
5. If you are running ISPF Version 2 or earlier, edit the NNMVS panels
whose names begin "NNMP...". These are popups, and will not work
under ISPF Version 2 unless you change the )BODY line. Remove the
WINDOW(...) parameter from the )BODY line of each panel so that the
line just says )BODY or )BODY EXPAND(``), as the case may be.
Note: You may wish to customize the TNNMSERV tutorial panel to
include the names of all available NNTP servers at your site.
Now, to install:
6. Submit the ALLOAD JCL to allocate the load library from which the
executable program will be run. If you intend to place the executable
into an existing library, you can skip this step, but you should make
sure that there is no previous load module named NNMMAIN in the load
library of your choice before you proceed.
7. Submit the COMPILE JCL to compile all the C sources and create the
executable NNMVS load module.
The first time you run this you can expect a return code of 8 from
the linkedit. Like SMP/E, this is OK if the only reason is an IEW0342
because the "INCLUDE SYSLMOD(NNMMAIN)" did not find an existing load
module. If you get IEW0132 (unresolved external reference) or
IEW0241 (ESD type definition conflict), your linkedit went awry.
Don't use the resultant load module. Check the libraries you
specified on the link step to see what went wrong.
In the future, if you have to recompile individual modules, you can use
the same JCL to compile only those modules, and the link will include
the new modules in the existing executable load module.
*********************************************************************
IMPORTANT: If you are running TCP/IP V2R2 or higher on MVS, you must
change the following library names in the compile and link JCL:
TCPIP.COMMMAC should be changed to TCPIP.SEZACMAC
TCPIP.COMMTXT should be changed to TCPIP.SEZACMTX
*********************************************************************
Note: If you have defined C370V1 in the NNUSER header file, you must
also include the system linklist load library or libraries containing
ISPLINK, ISPEXEC and IKJEFF18 when linking. Otherwise you may delete
the lines from the linkedit JCL that reference them.
Note: You need not include the PASCAL libraries or the AMPZMVSB
module if you are using TCP/IP Version 2 or higher, in which case
you must also define TCPIPV2 in the NNUSER headerfile.
8. Copy the HELP member of the CNTL library into the data set which
will be allocated to ddname NNBATHLP by the NNMVS batch mode JCL
procedure. This data set contains the text printed by the batch HELP
command. The distributed proc calls this 'NNMVS.HELP' - change it to
match the name of your data set (sequential, or member of a PDS).
9. Copy the NNMVS (or NNMVSC or NNMVSP) and NNMMAIL execs into your
installation CLIST or REXX library. Also copy the NNMVSL exec if
you want access to Leonard Woren's experimental multiple-server dialog.
10. If you use the NNMVSP version of the exec, copy the NNMVSHLP
member of the CNTL PDS into your installation TSO HELP library
under the same name as you gave the exec, so folks can type HELP xxx
where xxx is the name of the exec. If you have local help that you
want to include (like names of local servers, posting guidelines,
or whatever), create a HELP member called NNMVSLOC and install it
in the same library.
11. Copy all the members of the panel PDS into the ISPF panel library
specified in the NNMVS exec.
--------------------------------------------------------------------
Note: Make sure that the C/370 run time library is available,
either in the system link list or in the ISPLLIB concatenation,
before attempting to run NNMVS.
If the C/370 runtime library is not in the link list or otherwise
available to ISPF at execution time, you may arrange for it to be
allocated via LIBDEF in the NNMVS exec (I haven't tried this).
--------------------------------------------------------------------
Questions? Comments? Suggestions? Gripes? Requests? Musings?
You can communicate all of these via the LISTSERV mailing list
NNMVS-L, maintained at VM.USC.EDU. To get on this list, send mail to
LISTSERV@USCVM (or LISTSERV@VM.USC.EDU) with the following line in
the message body:
SUBSCRIBE NNMVS-L firstname lastname
Please keep in mind that further requests (e.g. to unsubscribe from
the list) must be sent to the LISTSERV address, *not* to the list.
The response you'll get from the SUBSCRIBE message will tell you
about this and more - so be sure to save it.
--------------------------------------------------------------------
Please email all other correspondence to...
Steve Bacher <seb@draper.com> or <seb1525@mvs.draper.com>
./ ADD NAME=$CHANGES,SSI=01050004
New Features in V3
Newsgroup article management is radically different, which should
result in improvements in response time and memory usage, as well
as avoiding out-of-memory abends.
A new pseudo-browse interface replaces the BRIF code, enabling
more commands while browsing a news article.
The PRT command is implemented, similar to EXTRACT except that it
prints to the SYSOUT class of your choice.
You have the option of letting the cursor remain next to the most
recently selected newsgroup or article.
New commands to simplify debugging have been added.
Additional installation-time customization for different levels
of ISPF.
Miscellaneous bug fixes and feature tweaks.
Latest Fixes to V2 R4
NNMCLRNG.C: - Fix memory leak when exiting from NNMVS.
NNMDLANG.C: - Fix 0C4 in "new newsgroups" function when the server
has duplicate entries in the active.times file.
- Check for bad output from news server's active file
in the NNTP LIST command, adjust counts and display a
nasty message so the user can nag the administrator.
NNMBPEXT.C: - Fix bug whereby all article headers were being
retrieved even when EXTRACT UNREAD was requested
in a batch job, causing excessive resource usage
and memory blowouts.
New Features In V2 R4
* Memory usage has been improved significantly.
* Handling of missing/expired articles has been improved.
* Miscellaneous Bug Fixes
* Enhancements to NNMVSP Exec
New Features In V2 R3 M2
* New commands:
- SORT Subject / Number - in article viewing mode, you may use this
command to sort the article display by subject or return it to the
default article-number order. Note that this may require a lot of
processing, both to retrieve article titles and to perform the
sorting, which tries to match messages up with "re:" replies.
When the LOCATE command is issued from an article display in this
mode, it takes a character string rather than a number.
- QUIT - from almost any panel, terminates NNMVS immediately.
It works like repeated END's, which means that it will save
your NEWSRC file. (QUIT from display-new-newsgroups or
display-bogus-newsgroups skips updating NEWSRC, though, for
your protection.)
* Miscellaneous changes:
The MARKALL and UNMARKALL commands now prompt you as to whether
you want to mark all the articles in the newsgroup or just the
ones currently shown in the table.
* The extra blank line that used to appear at the bottom of articles
is gone. There may be some effects on article extraction,
particularly when append mode is used, but in general this means
that what you get is more like what is really out there.
* In POST and MAIL, the format of the inserted message and the
dashed line separating the signature from the body have been
changed to be more in accordance with standard practice.
* Even more tweaking of missing article handling. It's better
than it was, and may even be considered acceptable now.
* Removed Features
Apologies: The PATH variable in batch has been removed.
It was of dubious value (I'm sure you don't miss it).
Basically, we needed the slot to implement subject sorting.
New Features In V2 R3 M1
* A user option to turn automatic scrolling on or off in the
newsgroup and article display tables has been added.
* In POST and MAIL, headers are no longer inserted into the text of
your reply. Instead, a message of the form
"In article <messageid> on <date>, <author> writes:"
is inserted.
* Remaining bugs and pitfalls of missing articles are finally
cleared up (hopefully).
* The ONLY and FIND commands in article display mode will cause
fetching of article headers if you are in "A" (all articles) mode.
* An OPTION operand has been added to the NNMVS exec, and support has
been added to NNMVS so that you will go directly to the requested
option if you use this and provide a number of other values.
* An attempt to protect users from crashing TCP/IP with multiple
copies of socket applications is included.
New Features In V2 R3
* New Commands for Controlling Newsgroup and Article Displays
Note: In the following descriptions of operands, "strings" are
unquoted single words or strings quoted with either single or double
quotes. Case is ignored.
The following new commands are available on the newsgroup display:
ORDER {Alphabetic/List} - specify the order in which the groups are
listed. The initial setting is A (alphabetic). You may change to
L (list) to view the newsgroups in the same order as the NNTP
server's active file (what the NNTP "LIST" command returns).
ONLY "string" - limit the newsgroup display to newsgroups with
"string" in the name. Type ONLY with no operands to restore
the display to all newsgroups (or registered, depending).
FIND "string" {NEXT/PREV/FIRST/LAST} - position the newsgroup
display to the next, previous, first or last group which has
"string" in the name. FIND with no operands repeats the find.
The following new commands are available on the article display:
ONLY "string" - limit the article display to articles with
"string" in the subject. Type ONLY with no operands to restore
the display to all articles (read or unread, depending).
FIND "string" {NEXT/PREV/FIRST/LAST} - position the article
display to the next, previous, first or last article which has
"string" in the subject. FIND with no operands repeats the find.
* New Options for Navigating Article Views
The following new commands are available from article browse:
NEXTU or NU - like NEXT but goes to the next unread article.
NEXTT or NT - like NEXT but goes to the next article currently in
the table. When you use ONLY to filter the article
display, NEXTT honors the filter. NEXT doesn't.
NEXTS or NS - like NEXT but goes to the next article in the current
subject thread.
PREVU(PU), PREVT(PT), PREVS(PS) are analogous to the above.
FIRSTSUBJ or FS - goes to the first article in the current
subject thread.
LASTSUBJ or LS - goes to the last article in the current
subject thread.
NEWSUBJ or NS - goes to the first unread article of a subject
other than the current thread.
SUBJECT or SUBJ - displays or changes the current subject.
* Prompting to Protect Existing Data Sets on EXTRACT
When you use the EXTRACT command, if the data set already exists
you will get a pop-up asking you to confirm that you want to
reuse the data set. Simply press ENTER to do so.
* Changes To Commands
The NNTP command may now be specified like this:
NNTP - by itself, puts you in the NNTP panel, as before
NNTP nntp-command - executes NNTP command immediately
For example: NNTP GROUP COMP.LANG.LISP
NNTP HELP
The OPTIONS command has been changed to take you to a menu of
general options. The RFC822 header settings are now option 1.
You can type OPT 1 to go directly there if you don't want to
see the extra panel. Also, in BROWSE, you can type HEADERS
(or HEADER) instead of OPTION to go directly to the RFC822
header setting panel.
In addition to RFC822 header display options, you may now specify
how you want screen displays to tell you about operations in process.
(There are some fancy new ways that NNMVS can do this.)
You can also control the prompting for overwriting on EXTRACT.
* Changes to Selection Codes
When you select "A" to see all the articles in a newsgroup,
NNMVS will fill in the title lines. No more empty lines.
To save processing, it will get only those that are necessary
to fill your screen. Scrolling down (or up) will get the next
batch - this will appear to be slower.
Also, only those articles that have actually been fetched (not
just the headers) will be retained in the table when you switch
back to using "S" to look at the articles in the newsgroup.
Note that whether you select "A" or "S" will affect subject
searches. If you selected "S", subject searches will be limited
to unread or already-retrieved articles. If you selected "A",
subject searches will retrieve previously read articles, and
potentially take longer.
You can select "N" to view only new (unseen) articles. "N" is
like "S" except that articles are removed from the display once
they are read whenever you reenter the article display or change
the viewing criteria.
The "Z" option, which will remain undocumented for now, is similar
to the "A" option except that it retrieves NO articles headers,
read or unread. Good for quick entry into a huge newsgroup, but
not very good at recording the correct status of the articles.
You can select "C" to cancel an article by posting a control request
to the server. You must be the original author (poster) of the
article to be allowed to cancel it. Cancellation is implemented
by sending a control message to the NNTP server.
* POST, FOLLOWUP and REPLY now allow you to specify a Reply-to email
address and a signature file. In addition, you may specify a
Followup-to list of newsgroups on POST or FOLLOWUP.
* FOLLOWUP and REPLY now follow the RFC1036 rules for generating
the default lists of newsgroups to post to and mail address to
reply to. FOLLOWUP even checks if the Followup-to: header says
"poster" or contains an email address, and strongly suggests
that you email instead of posting. Since BITNET postings dont
conform to RFC standards, the actual From: address is displayed
for REPLY in case you need to type it in.
* New Batch mode variable CHECKPOINT allows you to control whether the
NEWSRC file gets rewritten on every change or just at the end of a
batch run. Good for preventing NEWSRC wipeouts on 322 abends.
* Support for Multiple NNMVS's in a Single TSO Session
(assuming that they're talking to two different servers and
that you have the required TCP/IP multitasking socket support
APAR from IBM).
Basically, it dynamically generates a ddname for the newsrc file,
and you can specify different newsrc files, so there you go.
Warning: PIE users - DO NOT run 2 NNMVS's from different PIE
sessions - the IBM TCP/IP fix doesn't work for this! Use ISPF
split screen to do it.
* Optional Driver CLIST and REXX exec using XPROC to specify
parameters in CLIST-style Syntax
See installation instructions for details.
./ ADD NAME=$MISC,SSI=01030003
Miscellaneous Notes and Gotchas
========================================================================
* C/370 Kanji Feature
If your C/370 was not installed properly (e.g. you assumed that CBIPO
would take care of everything - you wretched fool!), it is possible
that you have the wrong national language for messages. This will
become apparent as soon as you fail to open a file, since the C/370
perror() function will write gibberish to stderr. To fix this, bug
your MVS systems programmer to reinstall C/370, e.g. with JDL1214
and without JCLB212 (for V2R1). It may be more complicated than that.
========================================================================
* C/370 Attention Handling
C/370 doesn't handle PA1 (attention) interrupts properly - in fact,
it completely screws them up, so you end up in an unbreakable loop
when you try to break out of a C/370 application running under ISPF
that uses the TCP/IP socket library.
As a temporary circumvention, you should apply a zap to module IBMBLIIA
in your run-time load library. The zap for C/370 V2R1, for example,
looks like this:
NAME IBMBLIIA IBMBLII1
VER 2250 0A60
REP 2250 1BFF
I.E., find the SVC 96 (STAX) instruction and NOP it.
Go ahead and apply it (preferably to a copy of IBMBLIIA in a user
library from which you run your favorite C/370 application, like
NNMVS, for example). Now you can feel free to do anything you like,
because you can always attention out.
If you find that you need this zap, please make sure that IBM hears
from you about the problem. The more customers they hear from, the
more likely it is that something will be done to fix it.
Be aware that this turns off attention handling entirely - but this
has turned out to be the only desirable behavior. Note that SIGINT
handling has never worked in C/370. If you don't believe this, then
just compile and run the sample program in member SIGFAIL.
./ ADD NAME=ALLOAD,SSI=01040000
//JOBNAME JOB ACCOUNT,'NAME'
//* */
//* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
//* */
//* This software is provided on an "AS IS" basis. All warranties, */
//* including the implied warranties of merchantability and fitness, */
//* are expressly denied. */
//* */
//* Provided this copyright notice is included, this software may */
//* be freely distributed and not offered for sale. */
//* */
//* Changes or modifications may be made and used only by the maker */
//* of same, and not further distributed. Such modifications should */
//* be mailed to the author for consideration for addition to the */
//* software and incorporation in subsequent releases. */
//* */
//*
//* Allocate NNMVS load library before install
//*
//NNALLOC PROC BS='6233',U='3380',V='',
// PRI='100',SEC='100',DIR='35'
//*
//IEFBR14 EXEC PGM=IEFBR14
//ALLOCDD DD DISP=(NEW,CATLG,DELETE),DSN=&LIB,
// DCB=(RECFM=U,BLKSIZE=&BS),
// SPACE=(&BS,(&PRI,&SEC,&DIR)),UNIT=&U,VOL=SER=&V
//*
// PEND
//*
//* The following step allocates the load library from which the
//* executable program will be run. If you intend to place the
//* executable into an existing library, you can skip this step.
//* Otherwise, the name must match the name used on the LOADLIB
//* parameter of the NNLINK procedure in the COMPILE JCL.
//*
//ALLOC1 EXEC NNALLOC,PRI=50,SEC=50,DIR=35,
// LIB='NNMVS.LOAD'
//*
./ ADD NAME=AUTH,SSI=01000039
#
# This file is used by NNTP clients (NNMVS) on this system to connect
# to news servers that require authentication, according to the new
# NNTO authorization protocol. It is ignored if the news server does
# not support this protocol. If the news server supports it, the user
# must be defined in the server host's /etc/passwd file and its uid
# must be the same as the uid of the user "nntp" - otherwise the server
# will disconnect the client.
#
# A server given here without a user or password will be accepted
# by NNMVS without an attempt to gain the server's authorization.
#
# serverhost user password
#
AUTHHOST NNTP JOSHUA
NOAUTHHOST
./ ADD NAME=COMPILE
//JOBNAME JOB ACCOUNT,'NAME'
//* */
//* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
//* */
//* This software is provided on an "AS IS" basis. All warranties, */
//* including the implied warranties of merchantability and fitness, */
//* are expressly denied. */
//* */
//* Provided this copyright notice is included, this software may */
//* be freely distributed and not offered for sale. */
//* */
//* Changes or modifications may be made and used only by the maker */
//* of same, and not further distributed. Such modifications should */
//* be mailed to the author for consideration for addition to the */
//* software and incorporation in subsequent releases. */
//* */
//*********************************************************************
//*
//* Compile some or all NNMVS C/370 sources to make the SYSLIN input
//* to the linkedit of the executable NNMMAIN load module.
//*
//NNCCL PROC MEMBER=,
// SRCLIB='NNMVS.C', NNMVS C source PDS
// HDRLIB='NNMVS.H', NNMVS C headers PDS
// COMMHDR='TCPIP.COMMMAC', C/370 TCP/IP headers
// C370HDR='SYS1.EDCHDRS', C/370 standard headers
// SYSMSGS='SYS1.EDCMSGS', C/370 messages file
// SYSMSGM='EDCMSGE', C/370 message member
// VIOUNIT=VIO, Temporary disk unit
// OUTCLAS='*', SYSOUT class
// CPARMS='SOURCE EXPMAC NOAGGR NOXREF', Compile parameters
// TEST=TEST TEST or NOTEST
//*
//CCOMP EXEC PGM=EDCCOMP,PARM='MARGINS(1,72) &TEST &CPARMS'
//SYSMSGS DD DISP=SHR,DSN=&SYSMSGS(&SYSMSGM)
//SYSIN DD DISP=SHR,DSN=&SRCLIB(&MEMBER)
//SYSLIB DD DISP=SHR,DSN=&COMMHDR
// DD DISP=SHR,DSN=&C370HDR
//USERLIB DD DISP=SHR,DSN=&HDRLIB
//SYSLIN DD DSN=&&LOADSET,UNIT=&VIOUNIT,DISP=(MOD,PASS),
// SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
//SYSPRINT DD SYSOUT=&OUTCLAS
//SYSCPRT DD SYSOUT=&OUTCLAS
//SYSUT1 DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
// SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
//SYSUT4 DD DSN=&&SYSUT4,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
// SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
//SYSUT6 DD DSN=&&SYSUT6,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
// SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
//SYSUT7 DD DSN=&&SYSUT7,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
// SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
//SYSUT8 DD DSN=&&SYSUT8,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
// SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
//SYSUT9 DD DSN=&&SYSUT9,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
// SPACE=(32000,(30,30)),DCB=(RECFM=VB,LRECL=137,BLKSIZE=882)
//SYSUT10 DD SYSOUT=&OUTCLAS
//*
// PEND
//*
//*********************************************************************
//*
//* Linkedit the executable NNMMAIN load module.
//*
//* Note: If C/370 V1R2 or higher, and you have therefore accepted
//* the "#define FETCH" in the NN header, you may delete
//* the line that includes the ISPLINK library.
//*
//* Note: If TCP/IP V2 or higher, remove the PASCAL link libraries
//* from the JCL and the AMPZMVSB card from the control deck.
//*
//NNLINK PROC LOADLIB='NNMVS.LOAD', Executable load library
// PLIBASE='SYS1.PLIBASE', PL/1 link library
// EDCBASE='SYS1.SEDCBASE', C/370 link library
// IBMBASE='SYS1.SIBMBASE', PL/1+C common library
// COMMTXT='TCPIP.COMMTXT', TCP/IP link library
// PASRUN3='SYS1.PAS.SAMPRUN3', PASCAL link library
// PASRUN1='SYS1.PAS.SAMPRUN1', PASCAL link library
// PASMSG1='SYS1.PAS.SAMPMSG1', PASCAL link library
// ISPLINK='ISP.V3R2M0.ISPLLIB', ISPLINK link library
// VIOUNIT=VIO, Temporary disk unit
// OUTCLAS='*', SYSOUT class
// LPARMS='LIST,LET,MAP', Linkedit parameters
// TEST=TEST TEST or NOTEST
//*
//LKED EXEC PGM=IEWL,PARM='AMODE(31),&TEST,&LPARMS'
//SYSPRINT DD SYSOUT=&OUTCLAS
//SYSLIB DD DISP=SHR,DSN=&PLIBASE
// DD DISP=SHR,DSN=&EDCBASE
// DD DISP=SHR,DSN=&IBMBASE
// DD DISP=SHR,DSN=&COMMTXT
// DD DISP=SHR,DSN=&PASRUN3 if TCP/IP V1 only
// DD DISP=SHR,DSN=&PASRUN1 if TCP/IP V1 only
// DD DISP=SHR,DSN=&PASMSG1 if TCP/IP V1 only
// DD DISP=SHR,DSN=&ISPLINK if C/370 V1R1 with #undef FETCH
//SYSLMOD DD DISP=SHR,DSN=&LOADLIB
//SYSUT1 DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
// SPACE=(32000,(30,30))
//*
// PEND
//*
//NNMADDNG EXEC NNCCL,MEMBER=NNMADDNG
//NNMADJUA EXEC NNCCL,MEMBER=NNMADJUA
//NNMALLAV EXEC NNCCL,MEMBER=NNMALLAV
//NNMALLOC EXEC NNCCL,MEMBER=NNMALLOC
//NNMAUTH EXEC NNCCL,MEMBER=NNMAUTH
//NNMBATCH EXEC NNCCL,MEMBER=NNMBATCH
//NNMBBEXP EXEC NNCCL,MEMBER=NNMBBEXP
//NNMBCONN EXEC NNCCL,MEMBER=NNMBCONN
//NNMBDECL EXEC NNCCL,MEMBER=NNMBDECL
//NNMBFLUS EXEC NNCCL,MEMBER=NNMBFLUS
//NNMBGCMD EXEC NNCCL,MEMBER=NNMBGCMD
//NNMBGDO EXEC NNCCL,MEMBER=NNMBGDO
//NNMBGEXP EXEC NNCCL,MEMBER=NNMBGEXP
//NNMBGTOK EXEC NNCCL,MEMBER=NNMBGTOK
//NNMBPDEC EXEC NNCCL,MEMBER=NNMBPDEC
//NNMBPDER EXEC NNCCL,MEMBER=NNMBPDER
//NNMBPELS EXEC NNCCL,MEMBER=NNMBPELS
//NNMBPEXE EXEC NNCCL,MEMBER=NNMBPEXE
//NNMBPEXT EXEC NNCCL,MEMBER=NNMBPEXT
//NNMBPFOR EXEC NNCCL,MEMBER=NNMBPFOR
//NNMBPHEL EXEC NNCCL,MEMBER=NNMBPHEL
//NNMBPIF EXEC NNCCL,MEMBER=NNMBPIF
//NNMBPLIS EXEC NNCCL,MEMBER=NNMBPLIS
//NNMBPMAR EXEC NNCCL,MEMBER=NNMBPMAR
//NNMBPNNT EXEC NNCCL,MEMBER=NNMBPNNT
//NNMBPPUT EXEC NNCCL,MEMBER=NNMBPPUT
//NNMBPQUE EXEC NNCCL,MEMBER=NNMBPQUE
//NNMBPQUI EXEC NNCCL,MEMBER=NNMBPQUI
//NNMBPREG EXEC NNCCL,MEMBER=NNMBPREG
//NNMBPSET EXEC NNCCL,MEMBER=NNMBPSET
//NNMBPVAR EXEC NNCCL,MEMBER=NNMBPVAR
//NNMBSOUT EXEC NNCCL,MEMBER=NNMBSOUT
//NNMBSYNT EXEC NNCCL,MEMBER=NNMBSYNT
//NNMBTEXT EXEC NNCCL,MEMBER=NNMBTEXT
//NNMBTRAS EXEC NNCCL,MEMBER=NNMBTRAS
//NNMBVGET EXEC NNCCL,MEMBER=NNMBVGET
//NNMBVPUT EXEC NNCCL,MEMBER=NNMBVPUT
//NNMBXFAR EXEC NNCCL,MEMBER=NNMBXFAR
//NNMBXFNG EXEC NNCCL,MEMBER=NNMBXFNG
//NNMCAR EXEC NNCCL,MEMBER=NNMCAR
//NNMCLRNG EXEC NNCCL,MEMBER=NNMCLRNG
//NNMCLRTX EXEC NNCCL,MEMBER=NNMCLRTX
//NNMCNRF EXEC NNCCL,MEMBER=NNMCNRF
//NNMCONN EXEC NNCCL,MEMBER=NNMCONN
//NNMCOPY EXEC NNCCL,MEMBER=NNMCOPY
//NNMDCAN EXEC NNCCL,MEMBER=NNMDCAN
//NNMDFAIL EXEC NNCCL,MEMBER=NNMDFAIL
//NNMDISC EXEC NNCCL,MEMBER=NNMDISC
//NNMDISPL EXEC NNCCL,MEMBER=NNMDISPL
//NNMDLANG EXEC NNCCL,MEMBER=NNMDLANG
//NNMDMAIL EXEC NNCCL,MEMBER=NNMDMAIL
//NNMDMENU EXEC NNCCL,MEMBER=NNMDMENU
//NNMDNG EXEC NNCCL,MEMBER=NNMDNG
//NNMDNNTP EXEC NNCCL,MEMBER=NNMDNNTP
//NNMDOIT EXEC NNCCL,MEMBER=NNMDOIT
//NNMDPOST EXEC NNCCL,MEMBER=NNMDPOST
//NNMDSOPT EXEC NNCCL,MEMBER=NNMDSOPT
//NNMDUMP EXEC NNCCL,MEMBER=NNMDUMP
//NNMESRVR EXEC NNCCL,MEMBER=NNMESRVR
//NNMESTNG EXEC NNCCL,MEMBER=NNMESTNG
//NNMFREEM EXEC NNCCL,MEMBER=NNMFREEM
//NNMGETDS EXEC NNCCL,MEMBER=NNMGETDS
//NNMGETM EXEC NNCCL,MEMBER=NNMGETM
//NNMGSRVL EXEC NNCCL,MEMBER=NNMGSRVL
//NNMIERR EXEC NNCCL,MEMBER=NNMIERR
//NNMIGET EXEC NNCCL,MEMBER=NNMIGET
//NNMINIT EXEC NNCCL,MEMBER=NNMINIT
//NNMISPF EXEC NNCCL,MEMBER=NNMISPF
//NNMIVGET EXEC NNCCL,MEMBER=NNMIVGET
//NNMIVPUT EXEC NNCCL,MEMBER=NNMIVPUT
//NNMMAIN EXEC NNCCL,MEMBER=NNMMAIN
//NNMMARR EXEC NNCCL,MEMBER=NNMMARR
//NNMMARU EXEC NNCCL,MEMBER=NNMMARU
//NNMNNTP EXEC NNCCL,MEMBER=NNMNNTP
//NNMONRF EXEC NNCCL,MEMBER=NNMONRF
//NNMOUTTX EXEC NNCCL,MEMBER=NNMOUTTX
//NNMPICK EXEC NNCCL,MEMBER=NNMPICK
//NNMPMSG EXEC NNCCL,MEMBER=NNMPMSG
//NNMPNG EXEC NNCCL,MEMBER=NNMPNG
//NNMQAR EXEC NNCCL,MEMBER=NNMQAR
//NNMQNG EXEC NNCCL,MEMBER=NNMQNG
//NNMRARH EXEC NNCCL,MEMBER=NNMRARH
//NNMRART EXEC NNCCL,MEMBER=NNMRART
//NNMRBFM EXEC NNCCL,MEMBER=NNMRBFM
//NNMRECON EXEC NNCCL,MEMBER=NNMRECON
//NNMRPERR EXEC NNCCL,MEMBER=NNMRPERR
//NNMSAVE EXEC NNCCL,MEMBER=NNMSAVE
//NNMSOCKT EXEC NNCCL,MEMBER=NNMSOCKT
//NNMSOPT EXEC NNCCL,MEMBER=NNMSOPT
//NNMSORT EXEC NNCCL,MEMBER=NNMSORT
//NNMSSRVR EXEC NNCCL,MEMBER=NNMSSRVR
//NNMSTRLC EXEC NNCCL,MEMBER=NNMSTRLC
//NNMSUMAT EXEC NNCCL,MEMBER=NNMSUMAT
//NNMTSO EXEC NNCCL,MEMBER=NNMTSO
//NNMUNALC EXEC NNCCL,MEMBER=NNMUNALC
//NNMUPDT EXEC NNCCL,MEMBER=NNMUPDT
//NNMVAR EXEC NNCCL,MEMBER=NNMVAR
//NNMVIEW EXEC NNCCL,MEMBER=NNMVIEW
//NNMVNG EXEC NNCCL,MEMBER=NNMVNG
//NNMVTX EXEC NNCCL,MEMBER=NNMVTX
//NNMXARTT EXEC NNCCL,MEMBER=NNMXARTT
//NNMXARTX EXEC NNCCL,MEMBER=NNMXARTX
//NNMXLIST EXEC NNCCL,MEMBER=NNMXLIST
//NNMXTX EXEC NNCCL,MEMBER=NNMXTX
//*
//* Link NNMVS load module. Like SMP/E, expect return code 8 when
//* doing this from scratch. Additional one-or-two-module links
//* will just replace the corresponding parts of the load module.
//*
//NNLINK EXEC NNLINK
//LKED.SYSLIN DD DISP=(OLD,DELETE),DSN=&&LOADSET
// DD *
INCLUDE SYSLMOD(NNMMAIN) if included first time, RC = 8
INCLUDE SYSLIB(AMPZMVSB) include if TCP/IP V1 only
ENTRY CEESTART
NAME NNMMAIN(R)
/*
./ ADD NAME=GRAMMAR,SSI=01030032
Grammar for NNMVS batch mode expressions.
/*-------------------------------------------------------------------*/
exp : choice
: "IF" exp "THEN" exp "ELSE" exp
/* IF flag THEN any ELSE any */
choice : relation
: choice logop relation /* flag | flag -> flag */
relation : value
: value relop value /* any > any -> flag */
value : quantity
: quantity quantity /* any any -> string */
quantity : term
: quantity addop term /* num + num -> number */
term : factor
: term mulop factor /* num * num -> number */
factor : constant
: variable /* FOO, if declared */
: unop factor /* - number -> number */
: "(" exp ")" /* (a + b * c > d | e ) */
constant : number
: string
: flag
unop : "+"
: "-"
: "!"
: "^"
addop : "+"
: "-"
mulop : "*"
: "/"
logop : "&"
: "|"
relop : "="
: ">"
: "<"
: "=="
: ">="
: "<="
: "!="
: "!>"
: "!<"
: "^="
: "^>"
: "^<"
: "IN"
variable : [a-z]*
number : [0-9]*
string : ""...""
flag : "TRUE"
: "FALSE"
: "ON"
: "OFF"
: "YES"
: "NO"
./ ADD NAME=HELP,SSI=010E0023
NNMVS Batch Mode Help
The following commands are available:
Top-Level Commands (in top-level mode, picking newsgroups)
FOR ALL | REGISTERED | UNREGISTERED {WHEN filter} commandlist;
where filter is any flag expression, evaluated per newsgroup,
and commandlist is a single command or DO; commands; END;
and the commands are per-newsgroup commands.
Per-Newsgroup Commands (in newsgroup mode, picking articles)
REGISTER
DEREGISTER
EXTRACT ALL | READ | UNREAD
QUERY
FOR ALL | READ | UNREAD | num {TO num} {WHEN filter} commandlist
where filter is any flag expression, evaluated per article,
and commandlist is a single command or DO; commands; END
and the commands are per-article commands.
Per-Article Commands (in article mode)
MARK {READ | UNREAD}
LIST
EXTRACT
QUERY
Miscellaneous Commands
IF condition THEN commandlist; {ELSE commandlist;}
where condition is any flag expression,
and commandlist is a single command or DO; commands; END;
and the commands are of the same mode as the one in which
the IF occurs.
PUT stringexpression # writes to output file
EXEC stringexpression # executes system command
NNTP stringexpression # transmits NNTP request
QUIT # terminates NNMVS
VARS # dumps current variables
{SET} variable { = } expression
Variable must be builtin or declared (see DECLARE below)
DECLARE variable {STRING | NUMBER | FLAG}
Note: DECLARE is the only command which is executed immediately.
All other commands are parsed and then the entire command
stream is executed only if no errors were detected.
Built-in Variables
LOCALPATH (string) - the hosts's local path name
DATETIME (string) - a time stamp
SERVER (string) - the name of the NNTP server host. Must be set
by the user before attempting a connection.
OUTFILE (string) - the name of an alternate output file for the
PUT commands and any commands (like NNTP) that
write text. The default setting, "", uses the
NNBATOUT DD. The value may be a data set name
(appended to) or in the form DD:ddname.
SERVERLIST (flag) - default is TRUE. Normally NNMVS will ask for
the current list of newsgroups from the NNTP
server when it begins processing newsgroups.
If you want to suppress this and just use the
groups named in NEWSRC, set SERVERLIST to FALSE.
Note that this may not save time, and in fact
may result in more processing, since NNMVS will
issue a GROUP request to each group requested
when it has not issued a LIST request.
AUTOREGISTER (flag) - default is FALSE. If this is set to TRUE,
new newsgroups will automatically be registered
in the NEWSRC file; otherwise they will be added
as unregistered newsgroups.
AUTODELETE (flag) - default is TRUE. If this is set to TRUE,
bogus newsgroups (groups in the NEWSRC file that
are not known to the server) will be deleted
from the NEWSRC file. Set this to FALSE to keep
such newsgroups in NEWSRC anyway.
ERROR (flag) - set to TRUE whenever an NNMVS batch command
operation fails. This is reset by each NNMVS
batch command, so grab it early.
EXACTCASE (flag) - default is FALSE. When this is FALSE, string
comparisons and tests succeed regardless of upper
or lower case. When this is set to TRUE, string
comparisons and tests succeed only if the strings
match exactly. Thus, "a" = "A" when EXACTCASE is
FALSE, but not when EXACTCASE is TRUE.
Variables meaningful to the EXTRACT command:
TABEXPAND (flag) - default is TRUE. Controls whether tab characters
are to be expanded on EXTRACT. (Note that tabs
are always expanded on PUT and LIST.)
APPEND (flag) - default is TRUE. Controls how articles are to be
extracted to sequential files by EXTRACT.
If APPEND is set to FALSE, existing sequential
files will be overwritten. This option is not
applicable to partitioned data sets (PDS's).
SEPARATOR (string) - default is the null string. If this is set to
a value other than the null string, the value
will be written between articles as a separator
line. Meaningful only when APPEND is TRUE.
BLANKSEP (flag) - default is FALSE. If TRUE, a blank line will be
generated before the separator line when it us
written out between articles. Otherwise the
separator line, if used, will follow the end of
the preceding article immediately. Meaningful
only when SEPARATOR and APPEND are set.
AUTOMARK (flag) - default is TRUE. When this is TRUE, the EXTRACT
operation will mark unread articles READ upon
successful extraction. It has no effect on
read articles or articles that failed extraction.
Set it to FALSE to prevent EXTRACT from marking
extracted articles read.
Variables meaningful in per-newsgroup mode and modes below:
GROUP (string) - the name of the current newsgroop.
REGISTERED (flag) - TRUE if newsgroup is registered.
NEWGROUP (flag) - TRUE if newsgroup is a new group (found by the
server LIST request but not in NEWSRC).
NOSUCHGROUP (flag) - TRUE if the newsgroup is "bogus" (in NEWSRC but
not found by the server LIST request).
COUNT (number) - the total number of articles in the newsgroup.
UNREAD (number) - the total number of new (unread) articles in the
newsgroup since the last time NNMVS used this
NEWSRC file.
FIRST (number) - the number of the first article in the group.
LAST (number) - the number of the last article in the group.
Variables meaningful in per-article mode and modes below:
NUMBER (number) - the current article number.
READ (flag) - TRUE if article has already been read.
MISSING (flag) - TRUE if article cannot be retrieved from server.
SUBJECT (string) - text of the Subject: header.
DATE (string) - text of the Date: header, with day name removed.
FROM (string) - text of From: header, author of the article.
MESSAGEID (string) - text of the Message-ID: header.
Expression Syntax
Expressions can be string expressions, number expressions, or
flag expressions. They can contain constants, variables, and
arithmetic or logical expressions. Strings may be concatenated
by placing one next to another, e. g. "foo" "bar".
String constants are enclosed in double quotes, with the backslash
acting as an escape with which to enclose embedded double quotes.
Numeric constants are integers only.
Flag constants may be represented as TRUE FALSE ON OFF YES NO.
Arithmetic operators: + - * / as well as unary + and -
Logical operators: & | as well as unary !
Relational operators: = != > < >= <= !> !<
(Note: == is an alias for =, and ^ may be used wherever ! is.)
For strings, the additional relational operator IN is available, e.g.
"foo" IN SUBJECT
The notation (IF expression THEN expression ELSE expression) is
allowed within expressions.
The following synonyms are accepted:
AND OR NOT EQ NE GT LT GE LE NG NL
The character # marks the beginning of a comment.
Extracting Files
EXTRACT writes the contents of one or more news articles out to a file
whose name is determined from a table allocated to DDname NNEXTTAB.
The format of the extract table is one line per newsgroup as follows:
groupname filename
where filename is a FULLY QUALIFIED name (quotes ignored) of one of
the following formats:
sequential data set name
wildcarded sequential data set name
wildcarded partitioned data set name
"Wildcarded" means that there is an asterisk "*" in a strategic
position in the file name. It must be preceded by at least one
alphanumeric character and may not be followed by one.
When the extraction is done, the asterisk is replaced with the number
of the article, zero padded on the left to fill out that segment of
the name.
Examples:
comp.group.one MYID.COMP.GROUP.SEQ.FOO*
comp.group.two MYID.COMP.GROUP.SEQ.ALL
comp.group.three MYID.COMP.GROUP.THREE.PDS(X*)
comp.group.four MYID.COMP.GROUP.NUMBER*.PDS(ANYMEM)
So...
comp.windows.x SEB1525.COMP.WINDOWS.X.TEXT.#*
defines a series of sequential data sets
COMP.WINDOWS.X.TEXT.#0000001
COMP.WINDOWS.X.TEXT.#0000002
etc.
PDS members can be expressed this way:
comp.os.vms COMP.OS.VMS.PDS(VMS*)
which gives
COMP.OS.VMS.PDS(VMS00001)
COMP.OS.VMS.PDS(VMS00002)
etc. If the article number takes more digits, it steals some
character positions away from the characters immediately preceding
the asterisk. For example, using the above model:
COMP.OS.VMS.PDS(VM142857)
The file need not already exist. If it does not, NNMVS will attempt
to guess the appropriate size when it allocates it, as the EXTRACT
command does in foreground.
./ ADD NAME=NNMVS,SSI=01030000
//* */
//* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
//* */
//* This software is provided on an "AS IS" basis. All warranties, */
//* including the implied warranties of merchantability and fitness, */
//* are expressly denied. */
//* */
//* Provided this copyright notice is included, this software may */
//* be freely distributed and not offered for sale. */
//* */
//* Changes or modifications may be made and used only by the maker */
//* of same, and not further distributed. Such modifications should */
//* be mailed to the author for consideration for addition to the */
//* software and incorporation in subsequent releases. */
//* */
//NNMVS PROC DEBUG=, say DEBUG=D for debugging
// LOADLIB='NNMVS.LOAD', must match LOADLIB in LINK job
// HELP='NNMVS.HELP', for batch HELP command
// NEWSRC='USERID.BATCH.NEWSRC', separate NEWSRC file
// EXTTAB='USERID.NNMVS.EXTTAB' table used by EXTRACT
//*
//* NNMVS batch mode.
//*
//NN EXEC PGM=NNMMAIN,PARM='-B&DEBUG'
//STEPLIB DD DISP=SHR,DSN=&LOADLIB
//NNNEWSRC DD DISP=OLD,DSN=&NEWSRC
//NNEXTTAB DD DISP=SHR,DSN=&EXTTAB
//NNBATHLP DD DISP=SHR,DSN=&HELP
//SYSPRINT DD SYSOUT=*
//SYSERR DD SYSOUT=*
//NNBATOUT DD SYSOUT=*,DCB=(RECFM=VB,LRECL=255)
//NNDEBUG DD SYSOUT=*
//NNBATIN DD DDNAME=SYSIN
//*
// PEND NNMVS
./ ADD NAME=NNMVSHLP,SSI=01020018
)F Function -
NNMVS is a newsreader for reading and posting articles in USENET
newsgroups.
NNMVS is an NNTP (network news transfer protocol) client that accesses
USENET news from a host machine elsewhere on your network that is
running an NNTP news server, and displays the news via ISPF. You must
tell NNMVS where this news server is; it does not know otherwise.
NNMVS remembers which articles you have read in a "newsrc" data set.
You specify the name of this data set on the primary menu, along
with the name of the news server host. Note that both of these
are given useful defaults when you start up NNMVS.
If you have never used NNMVS before, you use the blank or L option to
build up your NEWSRC file from a list retrieved from the server.
Then, to limit the list to your favorite newsgroups, you can register
(subscribe to) the ones you want while viewing the newsgroup list.
You can use L or blank all the time to enter NNMVS. However,
once you have used and built a NEWSRC file, you may wish to use a
different entry option to reduce startup time.
You can avoid retrieving the whole list by using the R option
to view only registered (subscribed) newsgroups, or the A option to
view all newsgroups listed in your NEWSRC file.
The disadvantage to using A or R is that you do not get the latest
additions to the news system when the newsgroup list shows up.
But there are ways to get around this. For example, you can use the
N option to get a list of newsgroups added since the last time you
retrieved the newsgroup list (i.e. used L or N).
If you want to go to a particular newsgroup directly, you can do so
via the G option. When you use this, you must provide the name of
the desired newsgroup.
)I NNMVSLOC - local NNMVS help goes in member NNMVSLOC
)X Syntax -
%NNMVS
SERVER('news server host')
GROUP('newsgroup name')
NEWSRC('data set name')
OPTION(A/G/L/N/O/P/R/X)
REGISTERSTATUS(Yes/No/Prompt)
FORCE
DEBUG
TEST
BATCH
BATCHIN('batch input file name')
BATCHOUT('batch output file name')
NEW
OLD
Required: none
Defaults: User is prompted (via ISPF panel) for all omitted values
Notes: If OPTION is given, then direct entry into the news
reader occurs, without display of the NNMVS primary menu.
However, if so, then SERVER and NEWSRC are required, and
GROUP is also required if OPTION(G) is specified.
If BATCH is given, then NEWSRC is required.
)O Operands -
))SERVER('news server host')
The hostname of the machine running the news server.
Note that an IP address may be specified, but this
is obviously not recommended.
If an asterisk "*" is specified as the server name,
an experimental dialog is invoked which displays an
ISPF table of news servers with associated NEWSRC
data set names. You select the news server you want
(or add a line associating that server with a specific
NEWSRC file). This feature is courtesy of Leonard Woren
(LDW@MVSA.USC.EDU, SHARE installation code USC).
))GROUP('newsgroup name')
The name of a specific newsgroup you want to see,
rather than the list of all newsgroups. If you specify
this, it will merely fill in the corresponding field of
the NNMVS primary menu, unless you also specify the
keyword OPTION(G) and values for SERVER and NEWSRC.
))NEWSRC('data set name')
The name of your "newsrc" file, a sequential data set
which keeps track of which articles you've already read
in which newsgroups. If this data set does not exist,
NNMVS will create it.
It is a good idea to use the same NEWSRC file all the
time for one news server, but to use separate NEWSRC
files for different news servers (should there be any).
If you specify this, it will merely fill in the
corresponding field of the NNMVS primary menu, unless
you also specify values for SERVER and OPTION.
If an asterisk "*" is specified as the NEWSRC name,
an experimental dialog is invoked which displays an
ISPF table of news servers with associated NEWSRC
data set names. You select the news server you want
(or add a line associating that server with a specific
NEWSRC file). This feature is courtesy of Leonard Woren
(LDW@MVSA.USC.EDU, SHARE installation code USC).
))OPTION(A/G/L/N/O/P/R/X)
The initial option to start up NNMVS without seeing
the primary menu, where the meanings of the letters
are those as displayed on the menu:
L - List all newsgroups from server
N - List new newsgroups from server since last N or L
A - Show items from all newsgroups listed in NEWSRC file
R - Show items from registered newsgroups in NEWSRC file
G - Go directly to the newsgroup named by operand GROUP
P - Enter native NNTP protocol commands
O - Specify NNMVS options defaults
X - Exit NNMVS
If you specify this, you must also specify values for
SERVER and NEWSRC. Also, if you specify OPTION(G), you
must provide a value for the GROUP keyword.
))REGISTERSTATUS(Yes/No/Prompt)
When you specify OPTION(R), NNMVS decides whether to
get the current status of each registered newsgroup,
since it doesn't get that information for free as it
does when you use the "L" (list) option. Therefore,
it normally prompts you with a popup asking you if it
is OK to do this, since it takes time.
Specify REGISTERSTATUS(Y) to tell NNMVS to go ahead and
do this. REGISTERSTATUS(N) says not to. The default,
REGISTERSTATUS(P), tells NNMVS to prompt as it would if
you selected option R from the primary menu.
))FORCE
NNMVS tries to determine if there is a TCP/IP socket
application active elsewhere in your TSO environment
before starting up, to prevent TCP/IP errors. If it
tells you that there is another client active but in
truth there is none and you know it, you can use the
FORCE keyword to make NNMVS proceed whether it finds
this to be the case or not.
))DEBUG
Set debugging mode on. You must preallocate a file to
ddname NNDEBUG for this to work. This can be allocated
to the terminal or a log file. When debug mode is on,
messages describing memory allocation and deallocation
and NNTP commands sent are dumped to the debug file.
))TEST
Activate C/370 interactive test (INSPECT). NNMVS must
have been compiled with the TEST option for this to be
effective. Note that you can also issue the TEST command
inside NNMVS to get to INSPECT, again provided that NNMVS
was compiled with the TEST option.
))BATCH
Invoke NNMVS in batch mode. When BATCH is specified,
NEWSRC must also be specified. The files specified by
BATCHIN and BATCHOUT are allocated and you supply
NNMVS batch commands in the BATCHIN file (typically the
terminal). You specify the news server via the command
server = "foobar";
where foobar should be replaced with the actual name of
the NNTP server host.
Note that no batch commands will be executed until the
entire batch language program is read in and EOF is met.
For help with the batch language, execute NNMVS in batch
mode and supply the command "HELP".
))BATCHIN('batch input file name')
the data set allocated for input to NNMVS batch mode.
Default is * (the terminal).
Note that no batch commands will be executed until the
entire batch language program is read in and EOF is met.
For help with the batch language, execute NNMVS in batch
mode and supply the command "HELP".
))BATCHOUT('batch output file name')
the data set allocated for output from NNMVS batch mode.
Default is * (the terminal).
For help with the batch language, execute NNMVS in batch
mode and supply the command "HELP".
))NEW
Use a new (testing) release of NNMVS. This is dependent
upon your installation's procedures for providing
parallel releases of software for users to run online in
test mode.
))OLD
Use an old (backup) release of NNMVS. This is dependent
upon your installation's procedures for providing
parallel releases of software for users to run online in
test mode.
./ ADD NAME=SIGFAIL,SSI=01010054
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
static void
handler() {
printf("SIGINT handler has been called.\n");
exit(8);
}
static int
ask(question)
char *question;
{
char ans[81];
for (;;) {
printf("%s",question);
fgets(ans,79,stdin);
switch (ans[0]) {
case 'y':
case 'Y': return 1;
case 'n':
case 'N': return 0;
default: printf("Bad answer, %s\n",ans);
continue;
}
}
}
main(argc,argv)
int argc;
char **argv;
{
int sigp;
int loopp;
int i;
printf(
"This program demonstrates that SIGINT is not handled on MVS.\n");
printf(
"It does NOT prove or disprove anything about attention handling\n");
printf(
"in C/370 in general, except possibly for how output to stdout\n");
printf(
"and stderr are affected by an attention interruption.\n\n");
printf(
"At the end of the program, a line of output is written to each\n");
printf(
"of the two output files. If you see either one, that means that\n");
printf(
"C/370 has intercepted the attention, but you will observe that\n");
printf(
"it has not been handled by a SIGINT routine and it also has not\n");
printf(
"allowed the program to be terminated by the operating system.\n\n");
sigp = ask("Do you want to signal abort on interrupts? (y or n)");
loopp = ask("Do you want to loop forever without output? (y or n)");
if (sigp) {
printf("Doing signal(SIGINT,handler)\n");
if (signal(SIGINT,handler) == SIG_ERR)
perror("Could not set SIGINT");
}
printf("OK, hit PA1 now\n");
if (loopp) {
for (;;) ;
}
else {
for (i=0;i<5000;i++) {
printf("I=%d\n",i);
}
}
printf("I'm finished (on stdout)\n");
fprintf(stderr,"I'm finished (on stderr)\n");
}
./ ENDUP
?!
//C EXEC NNLOAD,TRK1='46',TO='C'
//SYSIN DD DATA,DLM='?!'
./ ADD NAME=NNMADDNG,SSI=01010043
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ADDNG")
#pragma csect(static,"NN$ADDNG")
#include "nn.h"
#define KEEP_NEWSGROUPS_IN_ALPHABETICAL_ORDER
/****** Create a new newsgroup. **************************************/
static struct newsgroup *
new_newsgroup(np,gname)
Rstruc nncb *np;
char *gname;
{
struct newsgroup *gp;
int gsize;
char temp [128];
gsize = offsetof(struct newsgroup, name) + strlen(gname) + 1;
sprintf(temp, "newsgroup %s", gname);
GETMAIN(gp, char, gsize, temp);
if (!gp) {
ERR2("There is not enough memory to add newsgroup %s.",gname);
return NULL;
}
memset(gp, 0, gsize);
strcpy(gp->name, gname);
ClearGroupStatus(gp);
np->last_added_newsgroup = gp;
return gp;
}
/****** Add newsgroup. ***********************************************/
struct newsgroup *
NNMaddng(np,gname)
Rstruc nncb *np;
char *gname;
{
Rstruc newsgroup *gp;
struct newsgroup *prev_gp;
struct newsgroup *next_gp;
int s;
/* If there are no newsgroups yet, make this the first one. */
/* If the newsgroup is currently in the newsgroup list, reuse it. */
/* Otherwise add it. */
if (np->first_newsgroup == NULL) {
if ((gp=new_newsgroup(np,gname))) {
np->first_newsgroup = gp;
np->current_newsgroup = gp;
np->last_newsgroup = gp;
}
return gp;
}
prev_gp = NULL;
next_gp = NULL;
#ifdef KEEP_NEWSGROUPS_IN_ALPHABETICAL_ORDER
/* Chances are this newsgroup will be right after the last one that
we added. Check there first. */
gp = np->last_added_newsgroup; /* search from last added */
if (!gp || strcmp(gname,gp->name) < 0) /* unless ours precedes it */
gp = np->first_newsgroup; /* then search from top */
for (; gp; gp = gp->next) {
s = strcmp(gname,gp->name);
if (s == 0) { /* equal */
np->current_newsgroup = gp;
return gp;
}
else if (s < 0) { /* ours is less than theirs */
next_gp = gp;
break;
}
else { /* ours is still greater */
prev_gp = gp;
next_gp = NULL;
}
}
#else
/* keep newsgroups in NEWSRC order - not currently implemented */
for (gp = np->first_newsgroup;
gp && strcmp(gname,gp->name) != 0;
gp = gp->next) ;
if (gp) { /* newsgroup already in list */
np->current_newsgroup = gp;
return gp;
}
next_gp = NULL;
prev_gp = np->last_newsgroup;
#endif
/* newsgroup not in list - add it now */
if ((gp=new_newsgroup(np,gname))) {
if (next_gp == NULL) np->last_newsgroup = gp;
else gp->next = next_gp;
if (prev_gp == NULL) np->first_newsgroup = gp;
else prev_gp->next = gp;
np->current_newsgroup = gp;
}
return gp;
}
./ ADD NAME=NNMADJUA,SSI=01140047
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ADJUA")
#pragma csect(static,"NN$ADJUA")
#include "nn.h"
/****** Adjust unread articles. **************************************/
void
NNMadjua(np,gp,count,first,last)
Rstruc nncb *np;
Rstruc newsgroup *gp;
int count; /* estimated article count */
int first; /* estimated first article number */
int last; /* estimated last article number */
{
VARK *vp;
VARK *vpfirst;
VARK *vplast;
char *nlp;
/* logic:
* case
* last article number went up: increment unread count
* update high number
* no need for new vector
* last article number went down: need an article vector to
* see what newsrc says about which now-gone items were unread
*
* case
* first article number went up: need an article vector to
* see what newsrc says about which now-gone items were unread
* first article number went down: impossible, nothing to do
*
*/
/* Do not change gp->high_number. The caller of NNMadjua does this.
NNMallav needs to see the old value. */
if (last > gp->high_number) {
gp->unread_count += (last - gp->high_number);
}
if (last < gp->high_number || first > gp->low_number) {
/* Recent or oldest articles were cancelled or expired */
/* Reset the count, since no GROUP request may be associated */
/*
* If NNTP LIST overriding NEWSRC spec, there is an unparsed
* newsrc line. If it's just of the form "<nnn" with nothing else,
* and nnn is less than the new "low number" from LIST,
* then bypass allocation of an article vector. Just set the
* unread count to the new high and low number.
*/
if ((nlp=gp->saved_newsrc_line)
&& *nlp == '<'
&& !*(nlp+1 + strspn(nlp+1,"0123456789\n"))
&& atoi(nlp+1) < first) {
gp->unread_count = count;
}
/*
* If the article count didn't come from the NNTP GROUP command,
* then estimate it from the NNTP LIST or NEWSRC range, but only
* if an article vector was allocated.
*/
else {
NNMallav(np,gp,first,last); /* Allocate article vector */
if (gp->article_vector && !GroupSelected(gp)) {
gp->article_count = 0;
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
if (IsPresent(*vp)) gp->article_count++;
}
}
}
}
else {
gp->article_count = count;
}
/* No last minute adjustment of unread count,
* since this produces bad results later.
* If the user doesn't like this, hack the newsgroup display, not
* the newsgroup structure. What about saving back to newsrc?
*/
/*
* if (gp->unread_count > gp->article_count)
* gp->unread_count = gp->article_count;
*/
return;
}
./ ADD NAME=NNMALLAV,SSI=011B0006
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ALLAV")
#pragma csect(static,"NN$ALLAV")
#include "nn.h"
/****** Parse NEWSRC line. *******************************************/
static void
parse_newsrc_line(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
register char *nlp = gp->saved_newsrc_line;
int newsrc_number1 = 0;
int newsrc_number2 = 0;
int previous_number2 = 0;
int newsrc_scan_count = 0;
int i;
int imin;
int imax;
/*
* Reset the unread count, throwing away the "newsrc_unread" value.
* Initially the whole article vector is unread, and we make each
* article read if it says so in the rest of the newsrc line.
* Anything outside of the range of the article vector is GONE,
* so we consider it READ (i.e. not unread).
*/
gp->unread_count = gp->vector_last - gp->vector_first + 1;
/* If there is no newsrc line to parse, that's all. This used to be
first in this routine, but that caused missing articles outside of
the vector range not to be un-unread. */
if (!nlp) {
if (np->debug_file)
fprintf(np->debug_file,"NNMallav: no saved newsrc line for %s\n",
gp->name);
return;
}
/* get next number thing */
while (*nlp) {
previous_number2 = newsrc_number2;
while (*nlp && isspace(*nlp)) nlp++;
switch (*nlp) {
case '\0': newsrc_number1 = MAX_INT;
newsrc_number2 = 0;
break;
case '<': sscanf(nlp," <%d %n", &newsrc_number2,
&newsrc_scan_count);
newsrc_number1 = 1;
nlp += newsrc_scan_count;
break;
case '|': sscanf(nlp," |%d=%d %n", &newsrc_number1,
&newsrc_number2,
&newsrc_scan_count);
nlp += newsrc_scan_count;
break;
case '{': nlp = strchr(++nlp,'}');
if (nlp) nlp++;
continue;
case '#': nlp = strchr(++nlp,'#');
if (nlp) nlp++;
continue;
default: sscanf(nlp," %d %n", &newsrc_number1,
&newsrc_scan_count);
newsrc_number2 = newsrc_number1;
nlp += newsrc_scan_count;
break;
}
/*
* For this range of articles marked unread, if it's in the range
* of the article vector, we do nothing (should have been UNREAD).
*/
/*
* For this range of articles marked read, if it's in the range
* of the article vector, we mark the status accordingly.
* If it's outside of the range of the article vector,
* do nothing - it's just missing somehow.
*/
imax = MAX(newsrc_number1,gp->vector_first);
imin = MIN(newsrc_number2,gp->vector_last);
for (i = imax; i <= imin; i++) {
SetRead(GETVARK(gp,i));
gp->unread_count--;
}
} /* end while */
/* We're finished parsing the newsrc line, so free it. */
if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
FREEMAIN(gp->saved_newsrc_line,"parsed newsrc line");
}
gp->saved_newsrc_line = NULL;
gp->saved_newsrc_data[0] = '\0';
return;
}
/****** Allocate articles for newsgroup. *****************************/
void
NNMallav(np,gp,first,last)
Rstruc nncb *np;
Rstruc newsgroup *gp;
int first;
int last;
{
VARK *oldvp = gp->article_vector;
VARK *newvp = NULL;
int oldfirst = gp->vector_first;
int oldlast = gp->vector_last;
int newfirst = first;
int newlast = last;
int oldvlen;
int newvlen;
int anum;
int commonfirst;
int commonlast;
/*
* if an article vector already exists, then:
*
* all articles from new.first to old.first - 1 (impossible?) are
* set from their newsrc status, or else "unread"
* all articles from old.first to new.first - 1 are UN-UNREAD.
* all articles from old.last + 1 to new.last are:
* set to "unread" if > old.high_number
* (remember, we don't reset those until after the artvec hacking)
* set to "missing" ("read") if <= old.high_number
* (or unknown, or ???)
* all articles from new.last + 1 to old.last are UN-UNREAD.
*/
if (np->debug_file) {
fprintf(np->debug_file,
"NNMallav: asking for article vector for %s (%d, %d)\n",
gp->name, first, last);
}
if (oldfirst == newfirst && oldlast == newlast) return;
newvlen = (last == 0 ? 0 : last - first + 1);
if (newvlen > 0) {
GETMAIN(newvp, VARK, newvlen, "article vector");
if (!newvp) {
fprintf(stderr,"Error allocating %d-article vector for %s\n",
newvlen, gp->name);
ERR1("There is not enough virtual memory available to proceed.");
return;
}
memset(newvp, 0, newvlen * sizeof(VARK));
}
else {
newfirst = 2147483647;
newlast = 0;
}
if (oldvp) { /* if article vector already exists */
commonfirst = MAX(oldfirst, newfirst);
commonlast = MIN(oldlast, newlast);
/*
* copy the vector slots over from the old vector
*/
for (anum=commonfirst; anum <= commonlast; anum++) {
newvp[anum-newfirst] = oldvp[anum-oldfirst];
}
/*
* all articles from new.first to old.first - 1 (impossible?) are
* set from their newsrc status, or else "unread"
* Rationale: buggy newsrc didn't account for existing items
* can't set from newsrc until NNMpnrl is executed, so set them
* to good old missing-unread
*/
for (anum = newfirst; anum <= newlast && anum < oldfirst; anum++) {
SetMissingUnread(newvp[anum-newfirst]);
}
/*
* all articles from old.first to new.first - 1 are UN-UNREAD.
* Rationale: old items have expired or been cancelled.
* Since they fall out of the vector, they don't get an explicit
* status, but they do have to be removed from the unread count.
*/
for (anum = oldfirst; anum <= oldlast && anum < newfirst; anum++) {
if (IsUnread(oldvp[anum-oldfirst])) {
gp->unread_count--;
}
}
/*
* all articles from old.last + 1 to new.last are:
* set to "unread" if > old.high_number
* Rationale: new items came in since last time we looked
* set to "missing" ("read") if <= old.high_number
* Rationale: items in range but don't exist, cancelled/expired
*/
for (anum = MAX(newfirst, oldlast + 1); anum <= newlast; anum++) {
if (anum > gp->high_number) SetUnread(newvp[anum-newfirst]);
else SetMissingRead(newvp[anum-newfirst]);
}
/*
* all articles from new.last + 1 to old.last are UN-UNREAD.
* Rationale: old items have expired or been cancelled.
* Since they fall out of the vector, they don't get an explicit
* status, but they do have to be removed from the unread count.
*/
for (anum = MAX(oldfirst, newlast + 1); anum <= oldlast; anum++) {
if (IsUnread(oldvp[anum-oldfirst])) {
gp->unread_count--;
}
}
FREEMAIN(oldvp,"old article vector");
}
else { /* no old article vector */
/*
* initialize the vector to all unknown and unread
*/
for (anum = newfirst; anum <= newlast; anum++) {
SetNull(newvp[anum-newfirst]);
}
}
oldvlen = gp->article_vector_len;
gp->article_vector = newvp;
gp->article_vector_len = newvlen;
gp->vector_first = first;
gp->vector_last = last;
/* If this is the first time that we have allocated the article
* vector, initialize it from the saved newsrc line if there is one.
* i.e. if the article vector is being allocated for the first time.
*/
if (oldvlen == 0) {
parse_newsrc_line(np,gp);
}
return;
}
./ ADD NAME=NNMALLOC,SSI=01050033
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ALLOC")
#pragma csect(static,"NN$ALLOC")
#include "nn.h"
/****** Allocate a data set. *****************************************/
Bool
NNMalloc(dsname,ddname,type,nitems)
char *dsname;
char *ddname;
enum data_set_type type;
int nitems;
{
int i;
int rc;
Bool try_new;
short primary_allocation ;
short secondary_allocation ;
short directory_blocks ;
short dsorg ;
__S99parms stuff99; /* The manual has it wrong. No "struct". */
TEXTUNIT *tu [17];
TEXTUNIT tu_dsn;
TEXTUNIT tu_ddn;
TEXTUNIT tu_member;
TEXTUNIT tu_stat;
TEXTUNIT tu_disp;
TEXTUNIT tu_perm;
TEXTUNIT tu_rtddn;
TEXTUNIT tu_rtorg;
TEXTUNIT tu_block;
TEXTUNIT tu_prime;
TEXTUNIT tu_sec;
TEXTUNIT tu_dir;
TEXTUNIT tu_recfm;
TEXTUNIT tu_lrecl;
TEXTUNIT tu_blksz;
TEXTUNIT tu_dsorg;
char *lparp;
char *rparp;
char dsnseq [81];
char member [81];
try_new = FALSE;
memset((char *)&stuff99,0,sizeof(__S99parms));
strcpy(member,"");
strcpy(dsnseq,dsname);
lparp = strchr(dsnseq,'(');
rparp = strchr(dsnseq,')');
if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
*lparp = '\0'; /* makes dsnseq the seq part only */
*rparp = '\0'; /* turns member into a string */
strcpy(member, lparp+1);
type = PDS;
}
for (;;) {
stuff99.__S99RBLN = 20;
stuff99.__S99VERB = S99VRBAL;
stuff99.__S99FLAG1 = S99NOCNV << 8;
stuff99.__S99ERROR = 0;
stuff99.__S99INFO = 0;
stuff99.__S99TXTPP = tu;
stuff99.__S99FLAG2 = 0;
i = 0;
tu[i++] = &tu_dsn;
tu_dsn.key = DALDSNAM;
tu_dsn.num = 1;
tu_dsn.ent.len = strlen(dsnseq);
copy_uppercase(tu_dsn.ent.prm,dsnseq);
tu[i++] = &tu_stat;
tu_stat.key = DALSTATS;
tu_stat.num = 1;
tu_stat.ent.len = 1;
*tu_stat.ent.prm = (try_new ? NEW : SHR);
tu[i++] = &tu_disp;
tu_disp.key = DALNDISP;
tu_disp.num = 1;
tu_disp.ent.len = 1;
*tu_disp.ent.prm = (try_new ? CATLG : KEEP);
tu[i++] = &tu_rtorg;
tu_rtorg.key = DALRTORG;
tu_rtorg.num = 1;
tu_rtorg.ent.len = 2;
if (*member) {
tu[i++] = &tu_member;
tu_member.key = DALMEMBR;
tu_member.num = 1;
tu_member.ent.len = strlen(member);
copy_uppercase(tu_member.ent.prm,member);
}
if (ddname && *ddname) {
tu[i++] = &tu_ddn;
tu_ddn.key = DALDDNAM;
tu_ddn.num = 1;
tu_ddn.ent.len = strlen(ddname);
copy_uppercase(tu_ddn.ent.prm,ddname);
tu[i++] = &tu_perm;
tu_perm.key = DALPERMA;
tu_perm.num = 0;
}
else {
tu[i++] = &tu_rtddn;
tu_rtddn.key = DALRTDDN;
tu_rtddn.num = 1;
tu_rtddn.ent.len = 8;
memset(tu_rtddn.ent.prm,' ',8);
}
if (try_new) {
switch (type) {
case PDS:
primary_allocation = (short)nitems;
secondary_allocation = primary_allocation;
directory_blocks = (short)((nitems/(12*36)+1)*36);
dsorg = DSORG_PO;
break;
case SEQ:
default:
primary_allocation = (short)nitems;
secondary_allocation = primary_allocation;
directory_blocks = 0;
dsorg = DSORG_PS;
break;
}
tu[i++] = &tu_block;
tu_block.key = DALBLKLN;
tu_block.num = 1;
tu_block.ent.len = 3;
memset(tu_block.ent.prm,0,3);
*(short *)(tu_block.ent.prm+1) = 6233;
tu[i++] = &tu_prime;
tu_prime.key = DALPRIME;
tu_prime.num = 1;
tu_prime.ent.len = 3;
memset(tu_prime.ent.prm,0,3);
*(short *)(tu_prime.ent.prm+1) = primary_allocation;
tu[i++] = &tu_sec;
tu_sec.key = DALSECND;
tu_sec.num = 1;
tu_sec.ent.len = 3;
memset(tu_sec.ent.prm,0,3);
*(short *)(tu_sec.ent.prm+1) = secondary_allocation;
tu[i++] = &tu_dir;
tu_dir.key = DALDIR;
tu_dir.num = 1;
tu_dir.ent.len = 3;
memset(tu_dir.ent.prm,0,3);
*(short *)(tu_dir.ent.prm+1) = directory_blocks;
tu[i++] = &tu_recfm;
tu_recfm.key = DALRECFM;
tu_recfm.num = 1;
tu_recfm.ent.len = 1;
*tu_recfm.ent.prm = RECFM_VB;
tu[i++] = &tu_lrecl;
tu_lrecl.key = DALLRECL;
tu_lrecl.num = 1;
tu_lrecl.ent.len = 2;
*(short *)tu_lrecl.ent.prm = 259;
tu[i++] = &tu_blksz;
tu_blksz.key = DALBLKSZ;
tu_blksz.num = 1;
tu_blksz.ent.len = 2;
*(short *)tu_blksz.ent.prm = 6233;
tu[i++] = &tu_dsorg;
tu_dsorg.key = DALDSORG;
tu_dsorg.num = 1;
tu_dsorg.ent.len = 2;
*(short *)tu_dsorg.ent.prm = dsorg;
}
tu[i] = (void *)0x80000000;
rc = svc99(&stuff99);
if (rc == 0) {
if (!(ddname && *ddname)) {
memcpy(ddname,(char *)tu_rtddn.ent.prm,8);
*(ddname+8) = ' ';
*(strchr(ddname,' ')) = '\0';
}
if (type == SEQ &&
tu_rtorg.ent.prm[0] != 0x40) {
fprintf(stderr,"%s: not a sequential data set\n",dsname);
return FALSE;
}
if (type == PDS &&
tu_rtorg.ent.prm[0] != 0x02) {
fprintf(stderr,"%s: not a partitioned data set\n",dsname);
return FALSE;
}
return TRUE;
}
else if (!try_new && nitems != 0 && stuff99.__S99ERROR == 0x1708) {
try_new = TRUE;
continue;
}
else {
NNMdfail(rc,&stuff99);
return FALSE;
}
}
}
./ ADD NAME=NNMAUTH,SSI=01070043
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@AUTH ")
#pragma csect(static,"NN$AUTH ")
#include "nn.h"
/****** Send authorization to news server. ***************************/
Bool
NNMauth(np)
Rstruc nncb *np;
{
#ifdef AUTHFILE
char *lp;
FILE *fp;
int display_rc;
Bool auth_error;
Bool connection_probably_closed;
char authdd [12];
char authline [260];
char host [65];
char user [65];
char pass [65];
/* Send authorization.
*
* NNTP numbers must be the following as defined in C News source:
*
* OK_AUTHSYS 280 authorization system OK
* OK_AUTH 281 authorization OK
* NEED_AUTHINFO 380 authorization is required
* NEED_AUTHDATA 381 <type> authorization data required (e.g. PASS)
* ERR_NOAUTH 480 authorization required for command
* ERR_AUTHSYS 481 authorization system invalid
* ERR_AUTHREJ 482 authorization data rejected
* ERR_CMDSYN 501 command syntax error
* ERR_COMMAND 500 command not implemented
* ERR_ACCESS 502 access to server denied
* ERR_AUTHBAD 580 authorization failed
*
* Me: AUTHINFO USER username
* Server: 381 PASS required
* or: 482 Authorization already completed
* or: 500 Command not recognized
*
* If 482, server does not accept our attempt to gain authorization.
*
* If 500, authorization is not needed or the server has never
* heard of authorization. Either way, we proceed as "authorized".
*
* If 381 ...
*
* Me: AUTHINFO PASS password
* Server: 281 Authorization OK
* or: 482 authorization data rejected
* or: 502 access to server denied
* or: 580 authorization failed
*
* If 502, the server has disconnected me and I should return FALSE.
* Otherwise, everything is OK, and I should return TRUE.
*
*/
lp = "None - local system error accessing authorization file";
auth_error = FALSE;
connection_probably_closed = FALSE;
*host = '\0';
*user = '\0';
*pass = '\0';
/* Read user and pass from auth file */
strcpy(authdd,"dd:");
if (!NNMalloc(AUTHFILE,authdd+3,SEQ,0)) { /* allocate as SHR */
auth_error = TRUE;
}
else {
if (!(fp=fopen(authdd,"r"))) {
perror(AUTHFILE);
auth_error = TRUE;
}
else {
for (;;) {
fgets(authline,sizeof(authline),fp);
if (feof(fp)) break;
if (ferror(fp)) {
fprintf(stderr,"Error reading %s\n",AUTHFILE);
auth_error = TRUE;
break;
}
if (authline[0] == '#') continue; /* ignore comments */
*host = '\0';
*user = '\0';
*pass = '\0';
sscanf(authline,"%s %s %s", host,user,pass);
uppercase_in_place(host);
if (EQUAL(host,np->nnserver)) break;
};
fclose(fp);
}
(void)NNMunalc(authdd+3);
}
if (!auth_error) {
if (*user == '\0') return TRUE; /* Don't do auth if no username */
sprintf(np->nntp_command,"AUTHINFO USER %s", user);
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
switch (np->nntp_message_num) {
case 381: /* PASS required */
break;
case 500: /* Command not recognized */
/* server does not support AUTHINFO - all clients OK */
return TRUE;
default: NNMrperr(np); /* Report protocol error */
auth_error = TRUE;
break;
}
}
if (!auth_error) {
sprintf(np->nntp_command,"AUTHINFO PASS %s", pass);
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
switch (np->nntp_message_num) {
case 281: /* authorization OK */
return TRUE;
case 502: /* access to server denied */
/* Also, we have been disconnected at this point. */
connection_probably_closed = TRUE;
auth_error = TRUE;
break;
default: NNMrperr(np); /* Report protocol error */
auth_error = TRUE;
break;
}
}
NNMesrvr(np); /* End server read */
if (auth_error) {
if (connection_probably_closed) {
ERR2("Authorization failed;\
The NNTP server at %s refuses to authorize you. \
Some news operations may fail.",\
np->nnserver);
np->connection_broken = TRUE;
NNMdisc(np); /* Complete disconnection */
return FALSE;
}
else {
if (np->batch_mode) {
fprintf(stderr,
"NNMVS could not obtain authorization from the NNTP server.\n");
fprintf(stderr,
"NNMVS will proceed, but some news operations may fail.\n");
fprintf(stderr,
"The response from server %s was:\n\n%s\n\n", np->nnserver,lp);
return TRUE;
}
else {
NNMivput(np,"NNSERVER ",np->nnserver,-1);
NNMivput(np,"NNSRVRSP ",lp, -1);
(void)NNMispf(np,"ADDPOP ");
(void)NNMispf(np,"DISPLAY PANEL(NNMPAUTH)");
display_rc = np->ispfrc;
(void)NNMispf(np,"REMPOP ");
if (display_rc == 0) return TRUE;
else {
NNMdisc(np);
return FALSE;
}
}
}
}
else return TRUE;
#else
return TRUE; /* no authorization file defined */
#endif
}
./ ADD NAME=NNMBATCH,SSI=01000017
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BATCH")
#pragma csect(static,"NN$BATCH")
#include "nn.h"
#include "nnbatch.h"
/****** Parse command. ***********************************************/
static void
parse_command(np,bp,proc)
Rstruc nncb *np;
Rstruc batch *bp;
CommandParser proc;
{
Rstruc newscmd *cmdp = NULL;
struct cmdtree *treep;
cmdp = (proc)(np,bp);
if (!cmdp) return;
/* If a newscmd structure was returned, add it to the cmd tree. */
GETMAIN(treep, struct cmdtree, 1, "command tree");
if (!treep) {
bp->input_errors++;
return;
}
treep->next = NULL;
treep->cmd = cmdp;
if (bp->treebottom == NULL) bp->treetop = treep;
else bp->treebottom->next = treep;
bp->treebottom = treep;
return;
}
/****** Process requests. ********************************************/
static void
process_requests(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Rstruc cmdtree *treep;
if (bp->treetop == NULL) {
fprintf(np->batch_outfile, "There is no processing to be done.\n");
}
for (treep = bp->treetop; treep; treep = treep->next) {
bp->runtime_error = FALSE;
(treep->cmd->proc) (np,bp,treep->cmd);
if (ferror(np->batch_outfile)) {
fprintf(stderr,"*** Error writing to batch output file ***\n");
}
SETB("ERROR",bp->runtime_error);
}
return;
}
/****** Flag unmatched END. ******************************************/
static struct newscmd *
flag_unmatched_end(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
NNMbsynt(np,bp,NULL,0,"END without matching DO seen");
return NULL;
}
/****** Flag invalid ISPLINK call. ***********************************/
static int
flag_invalid_isplink_call(service,argument)
char *service;
char *argument;
{
fprintf(stderr,
"*** Attempt to call ISPLINK in batch mode:\n%8.8s %8.8s\n",
service, argument);
return 20;
}
/****** Flag invalid ISPEXEC call. ***********************************/
static int
flag_invalid_ispexec_call(lenp,buf)
int *lenp;
char *buf;
{
fprintf(stderr,"*** Attempt to call ISPEXEC in batch mode:\n%*.*s\n",
*lenp, *lenp, buf);
return 20;
}
/****** NNMVS batch mode. ********************************************/
int
NNMbatch(np)
Rstruc nncb *np;
{
struct batch *bp;
char *timep;
char *cp;
CommandParser proc;
time_t ltime;
struct batch batch_struct;
static char reserved_words [] = {
"AND DECLARE DEREGISTERDO ELSE "
"END EQ EXEC EXTRACT FALSE "
"FOR GE GT HELP IF "
"IN LE LT MARK NE "
"NNTP NO NOT OFF ON "
"OR PUT QUERY QUIT REGISTER "
"SET THEN TO TRUE VARS "
"WHEN YES " };
if (!(np->batch_infile && np->batch_outfile)) {
fprintf(stderr,"NNMVS: Batch operation failed. Terminated.\n");
return 16;
}
#ifdef FETCH
np->isplink_pointer = (int (*) ())flag_invalid_isplink_call;
np->ispexec_pointer = (int (*) ())flag_invalid_ispexec_call;
#endif
time(<ime);
timep = ctime(<ime);
if ((cp=strchr(timep,'\n'))) *cp = '\0';
fprintf(np->batch_outfile,"NNMVS news client at %s - %s\n\n",
np->client_hostname, timep);
bp = &batch_struct;
np->batch_hook = bp;
memset(bp,0,sizeof(struct batch));
bp->reserved_words = reserved_words;
bp->mode = INITIAL_MODE;
bp->curtok.type = NO_TOKEN;
bp->nextok.type = NO_TOKEN;
bp->endproc = flag_unmatched_end;
#undef TRUE
#define TRUE (void *)(1)
/* Declare built-in variables along with initial values. */
/* globally valid */
NNMbdecl(np,bp,"LOCALPATH", STRING_SYMTYPE, np->client_hostname);
NNMbdecl(np,bp,"DATETIME", STRING_SYMTYPE, timep );
NNMbdecl(np,bp,"SERVER", STRING_SYMTYPE, "" );
NNMbdecl(np,bp,"OUTFILE", STRING_SYMTYPE, "" );
NNMbdecl(np,bp,"SERVERLIST", FLAG_SYMTYPE, TRUE );
NNMbdecl(np,bp,"AUTOREGISTER", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"AUTODELETE", FLAG_SYMTYPE, TRUE );
NNMbdecl(np,bp,"AUTOMARK", FLAG_SYMTYPE, TRUE );
NNMbdecl(np,bp,"ERROR", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"EXACTCASE", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"TABEXPAND", FLAG_SYMTYPE, TRUE );
NNMbdecl(np,bp,"APPEND", FLAG_SYMTYPE, TRUE );
NNMbdecl(np,bp,"SEPARATOR", STRING_SYMTYPE, "" );
NNMbdecl(np,bp,"BLANKSEP", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"CHECKPOINT", FLAG_SYMTYPE, TRUE );
/* for newsgroups only */
NNMbdecl(np,bp,"GROUP", STRING_SYMTYPE, "" );
NNMbdecl(np,bp,"REGISTERED", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"NEWGROUP", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"NOSUCHGROUP", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"COUNT", NUMBER_SYMTYPE, 0 );
NNMbdecl(np,bp,"UNREAD", NUMBER_SYMTYPE, 0 );
NNMbdecl(np,bp,"FIRST", NUMBER_SYMTYPE, 0 );
NNMbdecl(np,bp,"LAST", NUMBER_SYMTYPE, 0 );
/* for articles only */
NNMbdecl(np,bp,"NUMBER", NUMBER_SYMTYPE, 0 );
NNMbdecl(np,bp,"READ", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"MISSING", FLAG_SYMTYPE, FALSE );
NNMbdecl(np,bp,"SUBJECT", STRING_SYMTYPE, "" );
NNMbdecl(np,bp,"DATE", STRING_SYMTYPE, "" );
NNMbdecl(np,bp,"FROM", STRING_SYMTYPE, "" );
NNMbdecl(np,bp,"MESSAGEID", STRING_SYMTYPE, "" );
do {
if ((proc = NNMbgcmd(np,bp))) {
parse_command(np,bp,proc);
}
} while (!bp->eof);
if (bp->input_errors > 0) {
fprintf(np->batch_outfile, "\nNo processing due to input errors.\n");
return 12;
}
else {
fprintf(np->batch_outfile, "\n\nOpening NEWSRC...\n\n");
strcpy(np->newsrc_to_open,"DD:NNNEWSRC");
NNMonrf(np,NULL); /* Open NEWSRC file */
fprintf(np->batch_outfile, "\n\nProcessing requests...\n\n");
process_requests(np,bp);
fprintf(np->batch_outfile, "\n\nClosing NEWSRC...\n\n");
NNMcnrf(np,NULL,(Fool)TRUE); /* Close NEWSRC file */
}
/* Clean up any outfile hacking that may have been done. */
SETC("OUTFILE","");
(void)NNMbsout(np,bp); /* Set output file */
np->batch_hook = NULL;
return bp->request_errors;
}
./ ADD NAME=NNMBBEXP,SSI=01000017
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BBEXP")
#pragma csect(static,"NN$BBEXP")
#include "nn.h"
#include "nnbatch.h"
#define CLEAR_THING(X) memset((char *)&X, 0, sizeof(struct thing))
static void from_exp ();
static void from_choice ();
static void from_relation ();
static void from_value ();
static void from_quantity ();
static void from_term ();
static void from_factor ();
static void from_unop ();
static void from_addop ();
static void from_mulop ();
static void from_logop ();
static void from_relop ();
static void from_constant ();
static void from_variable ();
static void from_number ();
static void from_string ();
static void from_flag ();
/****** Free old value when replacing it with a new value. ***********/
#define free_old_value(A,B) /* */
/* Do nothing yet. This may not have been a malloc'd value...
*
* static void
* free_old_value(np,tp)
* Rstruc nncb *np;
* Rstruc thing *tp;
* {
*
* if (tp->typ == STRING_SYMTYPE) {
* FREEMAIN((char *)tp->val,"old intermediate expression string value");
* tp->val = NULL;
* }
*
* return;
* }
*/
/****** Case-insensitive string compare. *****************************/
static int
Ustrcmp(a,b)
register char *a;
register char *b;
{
register char A;
register char B;
while (*a || *b) {
A = toupper(*a++);
B = toupper(*b++);
if (A > B) return 1;
if (A < B) return -1;
}
return 0;
}
/****** Case-insensitive string search. ******************************/
static char *
Ustrstr(b,a)
register char *b;
register char *a;
{
register char *aa;
register char *bb;
if (!*a) return strchr(b,'\0');
for (;;) {
while (*b && toupper(*a) != toupper(*b)) b++;
if (!*b) return NULL;
aa = a;
bb = b;
while (*aa && *bb && toupper(*aa) == toupper(*bb)) {
aa++;
bb++;
}
if (!*aa) return a;
b++;
}
}
/****** Concatenate string values. ***********************************/
static void
cat(np,bp,tp,tp1,tp2)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Rstruc thing *tp1;
Rstruc thing *tp2;
{
char *strdata1;
char *strdata2;
char *newstr;
int newlen;
/* for now, just do a lot of getmains and freemains */
free_old_value(np,tp);
strdata1 = (char *)tp1->val;
strdata2 = (char *)tp2->val;
if (*strdata1 == '\0') {
tp->val = (ANYTYPE)tp2->val;
}
else if (*strdata2 == '\0') {
tp->val = (ANYTYPE)tp1->val;
}
else {
newlen = strlen(strdata1) + strlen(strdata2) + 1;
GETMAIN(newstr, 1, newlen, "new concatenated string");
if (!newstr) {
fprintf(np->batch_outfile,
"Error, no storage to concatenate strings: %s, %s\n",
tp1->val, tp2->val);
longjmp(bp->jump,ERROR_GETMAIN_FAILURE);
}
strcpy(newstr,(char *)tp1->val);
strcat(newstr,(char *)tp2->val);
tp->val = (ANYTYPE)newstr;
}
tp->typ = STRING_SYMTYPE;
free_old_value(np,tp1);
free_old_value(np,tp2);
return;
}
/*-------------------------------------------------------------------*/
static void
convert_to_string(np,bp,tp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
{
Fool tempflag;
char tempstr[17];
switch (tp->typ) {
case STRING_SYMTYPE: return;
case NUMBER_SYMTYPE:
sprintf(tempstr, "%d", (int)tp->val);
tp->val = (ANYTYPE)NNMcopy(np,tempstr);
tp->typ = STRING_SYMTYPE;
return;
case FLAG_SYMTYPE:
tempflag = (Fool)tp->val;
tp->val = tempflag ? (ANYTYPE)"TRUE"
: (ANYTYPE)"FALSE";
tp->typ = STRING_SYMTYPE;
return;
}
}
/*-------------------------------------------------------------------*/
static void
convert_to_number(np,bp,tp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
{
Fool tempflag;
switch (tp->typ) {
case NUMBER_SYMTYPE: return;
case FLAG_SYMTYPE:
tempflag = (Fool)tp->val;
tp->val = tempflag ? (ANYTYPE)1
: (ANYTYPE)0;
tp->typ = NUMBER_SYMTYPE;
return;
case STRING_SYMTYPE:
/* Note: This should be permitted if the string is all numerics,
* but for now it is always an error.
* If permitted, call free_old_value before altering.
*/
fprintf(np->batch_outfile,
"Type mismatch, cannot convert string to number: %s\n",
tp->val);
longjmp(bp->jump,ERROR_TYPE_MISMATCH);
}
}
/*-------------------------------------------------------------------*/
static void
convert_to_flag(np,bp,tp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
{
switch (tp->typ) {
case FLAG_SYMTYPE: return;
case NUMBER_SYMTYPE:
/* Note: This should be permitted if the number is 0 or 1,
* but for now it is always an error.
*/
fprintf(np->batch_outfile,
"Type mismatch, cannot convert number to flag: %d\n",
tp->val);
longjmp(bp->jump,ERROR_TYPE_MISMATCH);
case STRING_SYMTYPE:
/* Note: This should be permitted if the string is "0", "1",
* "TRUE", "FALSE", "ON", "OFF", "YES", or "NO",
* but for now it is always an error.
* If permitted, call free_old_value before altering.
*/
fprintf(np->batch_outfile,
"Type mismatch, cannot convert string to flag: %s\n",
tp->val);
longjmp(bp->jump,ERROR_TYPE_MISMATCH);
}
}
/*-------------------------------------------------------------------*/
static void
from_number(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Number p;
{
tp->val = (ANYTYPE)p->number1;
tp->typ = NUMBER_SYMTYPE;
return;
}
/*-------------------------------------------------------------------*/
static void
from_string(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
String p;
{
tp->val = (ANYTYPE)p->string1;
tp->typ = STRING_SYMTYPE;
return;
}
/*-------------------------------------------------------------------*/
static void
from_flag(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Flag p;
{
tp->val = (ANYTYPE)p->flag1;
tp->typ = FLAG_SYMTYPE;
return;
}
/*-------------------------------------------------------------------*/
static void
from_variable(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Variable p;
{
enum symtype type;
type = p->s;
tp->val = (ANYTYPE)NNMbvget(np,bp,p->variable1,type);
tp->typ = type;
return;
}
/*-------------------------------------------------------------------*/
static void
from_constant(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Constant p;
{
switch (p->r) {
case RHSTYPE_A: from_number(np,bp,tp,p->u.a.number1); break;
case RHSTYPE_B: from_string(np,bp,tp,p->u.b.string1); break;
case RHSTYPE_C: from_flag (np,bp,tp,p->u.c.flag1 ); break;
}
return;
}
/*-------------------------------------------------------------------*/
static void
from_factor(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Factor p;
{
struct thing t1;
switch (p->r) {
case RHSTYPE_A: from_constant(np,bp,tp,p->u.a.constant1); break;
case RHSTYPE_B: from_variable(np,bp,tp,p->u.b.variable1); break;
case RHSTYPE_C:
CLEAR_THING(t1);
from_factor(np,bp,&t1,p->u.c.factor2);
switch (p->u.c.unop1->op1) {
case ADD_OP:
convert_to_number(np,bp,&t1);
tp->val = t1.val;
tp->typ = NUMBER_SYMTYPE;
break;
case SUB_OP:
convert_to_number(np,bp,&t1);
tp->val = (ANYTYPE)
(-((int)t1.val));
tp->typ = NUMBER_SYMTYPE;
break;
case NOT_OP:
convert_to_flag(np,bp,&t1);
tp->val = (ANYTYPE)
(!((Fool)t1.val));
tp->typ = FLAG_SYMTYPE;
break;
}
break;
case RHSTYPE_D: from_exp(np,bp,tp,p->u.d.exp1); break;
}
return;
}
/*-------------------------------------------------------------------*/
static void
from_term(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Term p;
{
struct thing t1;
struct thing t3;
switch (p->r) {
case RHSTYPE_A: from_factor(np,bp,tp,p->u.a.factor1); break;
case RHSTYPE_B:
CLEAR_THING(t1);
CLEAR_THING(t3);
from_term (np,bp,&t1,p->u.b.term1 );
from_factor(np,bp,&t3,p->u.b.factor3);
convert_to_number(np,bp,&t1);
convert_to_number(np,bp,&t3);
switch (p->u.b.mulop2->op1) {
case MUL_OP:
/* how to detect overflow? */
tp->val = (ANYTYPE)
((int)t1.val * (int)t3.val);
break;
case DIV_OP:
if ((int)t3.val == 0) {
fprintf(np->batch_outfile,
"Arithmetic error, division by zero\n");
longjmp(bp->jump,ERROR_ZERODIVIDE);
}
tp->val = (ANYTYPE)
((int)t1.val / (int)t3.val);
break;
}
tp->typ = NUMBER_SYMTYPE;
break;
}
return;
}
/*-------------------------------------------------------------------*/
static void
from_quantity(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Quantity p;
{
struct thing t1;
struct thing t3;
switch (p->r) {
case RHSTYPE_A: from_term(np,bp,tp,p->u.a.term1); break;
case RHSTYPE_B:
CLEAR_THING(t1);
CLEAR_THING(t3);
from_quantity(np,bp,&t1,p->u.b.quantity1);
from_term (np,bp,&t3,p->u.b.term3);
convert_to_number(np,bp,&t1);
convert_to_number(np,bp,&t3);
switch (p->u.b.addop2->op1) {
case ADD_OP:
/* how to detect overflow? */
tp->val = (ANYTYPE)
((int)t1.val + (int)t3.val);
break;
case SUB_OP:
/* how to detect overflow? */
tp->val = (ANYTYPE)
((int)t1.val - (int)t3.val);
break;
}
tp->typ = NUMBER_SYMTYPE;
break;
}
return;
}
/*-------------------------------------------------------------------*/
static void
from_value(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Value p;
{
struct thing t1;
struct thing t2;
switch (p->r) {
case RHSTYPE_A: from_quantity(np,bp,tp,p->u.a.quantity1); break;
case RHSTYPE_B:
CLEAR_THING(t1);
CLEAR_THING(t2);
from_value (np,bp,&t1,p->u.b.value1);
from_quantity(np,bp,&t2,p->u.b.quantity2);
convert_to_string(np,bp,&t1);
convert_to_string(np,bp,&t2);
cat(np,bp,tp,&t1,&t2);
break;
}
return;
}
/*-------------------------------------------------------------------*/
static void
from_relation(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Relation p;
{
enum optype op;
struct thing t1;
struct thing t3;
switch (p->r) {
case RHSTYPE_A: from_value(np,bp,tp,p->u.a.value1); break;
case RHSTYPE_B:
CLEAR_THING(t1);
CLEAR_THING(t3);
from_value(np,bp,&t1,p->u.b.value1);
from_value(np,bp,&t3,p->u.b.value3);
/* If either value is a string,
* or operation is "IN", do string compare.
* Otherwise do numeric compare.
* Note: Currently we are case sensitive.
* This possibly should be changed, but
* not now...
*/
op = p->u.b.relop2->op1;
if (op == IN_OP
|| t1.typ == STRING_SYMTYPE
|| t3.typ == STRING_SYMTYPE) {
convert_to_string(np,bp,&t1);
convert_to_string(np,bp,&t3);
if (bp->exactcase) {
switch (op) {
case EQ_OP: tp->val = (ANYTYPE)
(strcmp((char *)t1.val,(char *)t3.val) == 0);
break;
case NE_OP: tp->val = (ANYTYPE)
(strcmp((char *)t1.val,(char *)t3.val) != 0);
break;
case GT_OP: tp->val = (ANYTYPE)
(strcmp((char *)t1.val,(char *)t3.val) > 0);
break;
case LT_OP: tp->val = (ANYTYPE)
(strcmp((char *)t1.val,(char *)t3.val) < 0);
break;
case GE_OP: tp->val = (ANYTYPE)
(strcmp((char *)t1.val,(char *)t3.val) >= 0);
break;
case LE_OP: tp->val = (ANYTYPE)
(strcmp((char *)t1.val,(char *)t3.val) <= 0);
break;
case IN_OP: tp->val = (ANYTYPE)
(strstr((char *)t3.val,(char *)t1.val)!=NULL);
break;
}
}
else {
switch (op) {
case EQ_OP: tp->val = (ANYTYPE)
(Ustrcmp((char *)t1.val,(char *)t3.val) == 0);
break;
case NE_OP: tp->val = (ANYTYPE)
(Ustrcmp((char *)t1.val,(char *)t3.val) != 0);
break;
case GT_OP: tp->val = (ANYTYPE)
(Ustrcmp((char *)t1.val,(char *)t3.val) > 0);
break;
case LT_OP: tp->val = (ANYTYPE)
(Ustrcmp((char *)t1.val,(char *)t3.val) < 0);
break;
case GE_OP: tp->val = (ANYTYPE)
(Ustrcmp((char *)t1.val,(char *)t3.val) >= 0);
break;
case LE_OP: tp->val = (ANYTYPE)
(Ustrcmp((char *)t1.val,(char *)t3.val) <= 0);
break;
case IN_OP: tp->val = (ANYTYPE)
(Ustrstr((char *)t3.val,(char *)t1.val)!=NULL);
break;
}
}
}
else {
convert_to_number(np,bp,&t1);
convert_to_number(np,bp,&t3);
switch (op) {
case EQ_OP: tp->val = (ANYTYPE)((int)t1.val == (int)t3.val);
break;
case NE_OP: tp->val = (ANYTYPE)((int)t1.val != (int)t3.val);
break;
case GT_OP: tp->val = (ANYTYPE)((int)t1.val > (int)t3.val);
break;
case LT_OP: tp->val = (ANYTYPE)((int)t1.val < (int)t3.val);
break;
case GE_OP: tp->val = (ANYTYPE)((int)t1.val >= (int)t3.val);
break;
case LE_OP: tp->val = (ANYTYPE)((int)t1.val <= (int)t3.val);
break;
}
}
tp->typ = FLAG_SYMTYPE;
break;
}
return;
}
/*-------------------------------------------------------------------*/
static void
from_choice(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Choice p;
{
struct thing t1;
struct thing t3;
switch (p->r) {
case RHSTYPE_A: from_relation(np,bp,tp,p->u.a.relation1); break;
case RHSTYPE_B:
CLEAR_THING(t1);
CLEAR_THING(t3);
from_choice (np,bp,&t1,p->u.b.choice1);
from_relation(np,bp,&t3,p->u.b.relation3);
convert_to_flag(np,bp,&t1);
convert_to_flag(np,bp,&t3);
switch (p->u.b.logop2->op1) {
case AND_OP:
tp->val = (ANYTYPE)
((Fool)t1.val && (Fool)t3.val);
break;
case OR_OP:
tp->val = (ANYTYPE)
((Fool)t1.val || (Fool)t3.val);
break;
}
tp->typ = FLAG_SYMTYPE;
break;
}
return;
}
/*-------------------------------------------------------------------*/
static void
from_exp(np,bp,tp,p)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc thing *tp;
Exp p;
{
struct thing t1;
struct thing t2;
struct thing t3;
switch (p->r) {
case RHSTYPE_A: from_choice(np,bp,tp,p->u.a.choice1); break;
case RHSTYPE_B:
CLEAR_THING(t1);
CLEAR_THING(t2);
CLEAR_THING(t3);
from_exp(np,bp,&t1,p->u.b.exp1);
from_exp(np,bp,&t2,p->u.b.exp2);
from_exp(np,bp,&t3,p->u.b.exp3);
convert_to_flag(np,bp,&t1);
if ((Fool)t1.val) {
tp->val = t2.val;
tp->typ = t2.typ;
}
else {
tp->val = t3.val;
tp->typ = t3.typ;
}
break;
}
return;
}
/****** Build object from ptree to return as run-time value. *********/
ANYTYPE
NNMbbexp(np,bp,treep,type)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc ptree *treep;
enum symtype type;
{
struct thing it;
CLEAR_THING(it);
bp->exactcase = GETB("EXACTCASE");
/* Define return point for run-time errors during evaluation. */
if (setjmp(bp->jump) != 0) {
bp->request_errors++;
bp->runtime_error = TRUE;
return NULL;
}
/* Get the value, whatever type it turns out to be. */
from_exp(np,bp,&it,treep->exp1);
/* Try to make the value match the requested type. */
switch (type) {
case STRING_SYMTYPE: convert_to_string(np,bp,&it); break;
case NUMBER_SYMTYPE: convert_to_number(np,bp,&it); break;
case FLAG_SYMTYPE: convert_to_flag (np,bp,&it); break;
}
/* Return the value. */
return it.val;
}
./ ADD NAME=NNMBCONN,SSI=01000038
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BCONN")
#pragma csect(static,"NN$BCONN")
#include "nn.h"
#include "nnbatch.h"
/****** Insure server name. ******************************************/
static void
insure_server_name(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
char *servername;
if (!*np->nnserver) {
servername = GETC("SERVER");
if (servername) {
strncpy(np->nnserver,servername,sizeof(np->nnserver));
}
}
return;
}
/****** Connect to server in batch mode. *****************************/
Bool
NNMbconn(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
if (!np->connected_to_server) {
insure_server_name(np,bp);
if (!NNMconn(np)) { /* Connect to server */
fprintf(np->batch_outfile,"Server connection failed.\n");
return FALSE;
}
}
return np->connected_to_server;
}
./ ADD NAME=NNMBDECL,SSI=01000011
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BDECL")
#pragma csect(static,"NN$BDECL")
#include "nn.h"
#include "nnbatch.h"
/****** Validate a variable name. ************************************/
static Bool
validate(np,bp,var)
Rstruc nncb *np;
Rstruc batch *bp;
char *var;
{
int varlen;
char *cp;
char vartest[MAX_RESERVED_WORD_LENGTH];
varlen = strlen(var);
if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
ERR2(
"A variable name must be between 1 and %d characters in length.",
MAX_SYMBOL_LENGTH);
return FALSE;
}
if (varlen >= MIN_RESERVED_WORD_LENGTH
&& varlen <= MAX_RESERVED_WORD_LENGTH) {
memset(vartest,' ',MAX_RESERVED_WORD_LENGTH);
memcpy(vartest,var,strlen(var));
for (cp = bp->reserved_words; *cp != ' '; cp += 10) {
if (memcmp(vartest,cp,MAX_RESERVED_WORD_LENGTH) == 0) {
ERR2(
"The name %s is reserved and cannot be used as a variable name.",
var);
return FALSE;
}
}
}
return TRUE;
}
/****** Declare a variable symbol. ***********************************/
struct symtab *
NNMbdecl(np,bp,var,type,val)
Rstruc nncb *np;
Rstruc batch *bp;
char *var;
enum symtype type;
ANYTYPE val;
{
Rstruc symtab *symp;
Rstruc symtab **sympref;
struct symtab *sympnew;
struct symtab *sympleft;
struct symtab *sympright;
int minimum_value_length;
int getlen;
int comp;
char vartest[MAX_SYMBOL_LENGTH];
if (!validate(np,bp,var)) {
NNMbsynt(np,bp,var,0,"Variable name cannot be declared");
return NULL;
}
memset(vartest,'\0',MAX_SYMBOL_LENGTH);
memcpy(vartest,var,strlen(var));
switch (type) {
case STRING_SYMTYPE: minimum_value_length = strlen((char *)val) + 1;
break;
case NUMBER_SYMTYPE: minimum_value_length = 12;
break;
case FLAG_SYMTYPE: minimum_value_length = 6;
break;
}
sympleft = NULL;
sympright = NULL;
sympref = &bp->symtabp;
while ((symp=*sympref)) {
switch ((comp=memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH))) {
case 0: /* equal */
NNMbsynt(np,bp,var,0,
"Variable being declared already exists");
return NULL;
case 1: /* greater */
sympref = &symp->right;
continue;
default: /* less */
sympref = &symp->left;
continue;
}
}
/* Allocate a new symbol table entry for this new symbol and
* add it to the tree.
*/
getlen = offsetof(struct symtab, symval) + minimum_value_length;
GETMAIN(sympnew, char, getlen, "new symbol table entry");
if (!sympnew) {
NNMbsynt(np,bp,var,0,"Not enough storage to declare symbol");
return NULL;
}
memcpy(sympnew->symvar, vartest, MAX_SYMBOL_LENGTH);
sympnew->left = sympleft;
sympnew->right = sympright;
sympnew->vallen = minimum_value_length;
*sympref = sympnew;
sympnew->type = type;
switch (type) {
case STRING_SYMTYPE:
strcpy(sympnew->symval,(char *)val);
if (np->debug_file)
fprintf(np->debug_file,
"NNMbdecl: %s set to '%s'\n",
sympnew->symvar, sympnew->symval);
break;
case NUMBER_SYMTYPE:
sympnew->symnum = (int)val;
if (np->debug_file)
fprintf(np->debug_file,
"NNMbdecl: %s set to %d\n",
sympnew->symvar, sympnew->symnum);
break;
case FLAG_SYMTYPE:
sympnew->symnum = (int)val ? 1 : 0;
if (np->debug_file)
fprintf(np->debug_file,
"NNMbdecl: %s set to %s\n",
sympnew->symvar,
sympnew->symnum ? "TRUE" : "FALSE");
break;
}
return sympnew;
}
./ ADD NAME=NNMBFLUS,SSI=01000035
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BFLUS")
#pragma csect(static,"NN$BFLUS")
#include "nn.h"
#include "nnbatch.h"
/****** Flush input line. ********************************************/
void
NNMbflus(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
/* This routine eats tokens, ignoring them, until it sees a
semicolon or a new line. */
if (np->debug_file) {
fprintf(np->debug_file,"Flushing rest of input line.\n");
}
bp->stop_at_newline = TRUE;
for (;;) {
if (!NNMbgtok(np,bp,TOKEN_FLUSH)) break; /* get token */
switch (bp->curtok.type) {
case EOF_TOKEN:
case EOL_TOKEN:
case SEMI_TOKEN: break;
default:
if (np->debug_file) {
fprintf(np->debug_file,"Ignoring token.\n");
}
continue;
}
break;
}
bp->stop_at_newline = FALSE;
return;
}
./ ADD NAME=NNMBGCMD,SSI=01000057
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BGCMD")
#pragma csect(static,"NN$BGCMD")
#include "nn.h"
#include "nnbatch.h"
#define BATCHPARSER(X) extern struct newscmd * \
X (struct nncb *, struct batch *)
BATCHPARSER (NNMbphel); /* Parse batch HELP command */
BATCHPARSER (NNMbpfor); /* Parse batch FOR command */
BATCHPARSER (NNMbpif ); /* Parse batch IF command */
BATCHPARSER (NNMbpels); /* Parse batch ELSE command */
BATCHPARSER (NNMbpque); /* Parse batch QUERY command */
BATCHPARSER (NNMbpreg); /* Parse batch REGISTER command */
BATCHPARSER (NNMbpder); /* Parse batch DEREGISTER command */
BATCHPARSER (NNMbpset); /* Parse batch SET command */
BATCHPARSER (NNMbpput); /* Parse batch PUT command */
BATCHPARSER (NNMbpexe); /* Parse batch EXEC command */
BATCHPARSER (NNMbpqui); /* Parse batch QUIT command */
BATCHPARSER (NNMbpnnt); /* Parse batch NNTP command */
BATCHPARSER (NNMbplis); /* Parse batch LIST command */
BATCHPARSER (NNMbpmar); /* Parse batch MARK command */
BATCHPARSER (NNMbpext); /* Parse batch EXTRACT command */
BATCHPARSER (NNMbpvar); /* Parse batch VARS command */
BATCHPARSER (NNMbpdec); /* Parse batch DECLARE command */
/****** Get command. *************************************************/
CommandParser
NNMbgcmd(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
char *cp;
struct token *tp;
CommandParser cproc;
Bool command_not_gotten = FALSE;
Bool assumed_set = FALSE;
for (;;) {
bp->stop_at_newline = FALSE; /* read lines until token found */
if (!(tp = PEEK())) { /* peek token */
command_not_gotten = TRUE;
}
else switch (tp->type) {
case EOF_TOKEN:
EAT();
return FALSE; /* OK, no more commands to process */
case WORD_TOKEN:
break; /* good, what a command should look like */
case EOL_TOKEN:
case SEMI_TOKEN:
EAT();
continue; /* keep looping */
case STRING_TOKEN:
EAT();
NNMbsynt(np,bp,NULL,0,
"Quoted string where command name expected");
command_not_gotten = TRUE;
break;
default:
EAT();
NNMbsynt(np,bp,tp->string,0,
"Invalid token where command name expected");
command_not_gotten = TRUE;
break;
}
break; /* continue only when ';' found */
}
/* Determine what the command is. If the command is not recognized,
* but it is the name of a declared variable, then assume it is SET
* and don't eat the token - let SET see it.
*/
if (!command_not_gotten) {
cp = tp->string;
if (EQUAL(cp,"HELP" )) cproc = NNMbphel;
else if (EQUAL(cp,"FOR" )) cproc = NNMbpfor;
else if (EQUAL(cp,"IF" )) cproc = NNMbpif ;
else if (EQUAL(cp,"ELSE" )) cproc = NNMbpels;
else if (EQUAL(cp,"QUERY" )) cproc = NNMbpque;
else if (EQUAL(cp,"REGISTER" )) cproc = NNMbpreg;
else if (EQUAL(cp,"DEREGISTER" )) cproc = NNMbpder;
else if (EQUAL(cp,"SET" )) cproc = NNMbpset;
else if (EQUAL(cp,"PUT" )) cproc = NNMbpput;
else if (EQUAL(cp,"EXEC" )) cproc = NNMbpexe;
else if (EQUAL(cp,"QUIT" )) cproc = NNMbpqui;
else if (EQUAL(cp,"NNTP" )) cproc = NNMbpnnt;
else if (EQUAL(cp,"LIST" )) cproc = NNMbplis;
else if (EQUAL(cp,"MARK" )) cproc = NNMbpmar;
else if (EQUAL(cp,"EXTRACT" )) cproc = NNMbpext;
else if (EQUAL(cp,"VARS" )) cproc = NNMbpvar;
else if (EQUAL(cp,"DECLARE" )) cproc = NNMbpdec;
else if (EQUAL(cp,"END" )) cproc = bp->endproc;
else if (NNMbvget(np,bp,cp,NO_SYMTYPE)) { /* if declared var name */
assumed_set = TRUE;
cproc = NNMbpset;
}
else {
NNMbsynt(np,bp,cp,0, "Command or variable name unknown");
command_not_gotten = TRUE;
}
}
if (!(EQUAL(cp,"ELSE"))) bp->ifcmd = NULL; /*Disallow unmatched ELSE*/
if (!assumed_set) EAT(); /* Swallow the command name if 'twas real */
if (command_not_gotten) {
fprintf(np->batch_outfile, "Rest of input line ignored.\n");
NNMbflus(np,bp); /* Flush rest of tokens on input line */
return FALSE;
}
return cproc;
}
./ ADD NAME=NNMBGDO,SSI=01000043
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BGDO ")
#pragma csect(static,"NN$BGDO ")
#include "nn.h"
#include "nnbatch.h"
#define MAGIC_END_COOKIE (void *)(1)
/****** Handle END command. ******************************************/
static struct newscmd *
handle_end(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
NNMbflus(np,bp); /* flush all tokens following END */
return MAGIC_END_COOKIE;
}
/****** Get commands, parse them and add to command tree. ************/
static struct cmdtree *
get_multiple_commands(np,bp,mode)
Rstruc nncb *np;
Rstruc batch *bp;
enum batchmode mode;
{
Rstruc newscmd *cmdp = NULL;
struct cmdtree *treep = NULL;
struct cmdtree *treetop = NULL;
struct cmdtree *treebottom = NULL;
CommandParser proc;
CommandParser save_endproc;
enum batchmode save_mode;
Bool bad_command = FALSE;
Bool end_found = FALSE;
save_mode = bp->mode;
bp->mode = mode;
save_endproc = bp->endproc;
bp->endproc = handle_end;
while (!bp->eof) {
proc = NNMbgcmd(np,bp); /* Get next command */
if (!proc) { /* If invalid command, continue */
bad_command = TRUE;
continue;
}
cmdp = (proc)(np,bp); /* Parse it returning command tree */
if (!cmdp) { /* If syntax error, continue */
bad_command = TRUE;
continue;
}
if (cmdp == MAGIC_END_COOKIE) { /* if END seen */
end_found = TRUE;
break;
}
/* If a newscmd structure was returned, add it to the cmd tree. */
GETMAIN(treep, struct cmdtree, 1, "DO command tree");
if (!treep) {
bp->input_errors++;
bad_command = TRUE;
continue;
}
treep->next = NULL;
treep->cmd = cmdp;
if (treebottom == NULL) treetop = treep;
else treebottom->next = treep;
treebottom = treep;
}
bp->endproc = save_endproc;
bp->mode = save_mode;
if (!end_found) {
NNMbsynt(np,bp,NULL,0,"No END found to match DO");
}
return treetop;
}
/****** Get a single command, parse it and make command tree. ********/
static struct cmdtree *
get_single_command(np,bp,mode)
Rstruc nncb *np;
Rstruc batch *bp;
enum batchmode mode;
{
Rstruc newscmd *cmdp = NULL;
struct cmdtree *treep = NULL;
struct token *tp;
CommandParser proc;
enum batchmode save_mode;
save_mode = bp->mode;
bp->mode = mode;
if (!(tp = PEEK())) return NULL;
/* Handle null command (e.g. IF x THEN; ELSE; ) */
if (tp->type == SEMI_TOKEN) return NULL;
proc = NNMbgcmd(np,bp); /* Get next command */
if (!proc) return NULL; /* If invalid command, error */
cmdp = (proc)(np,bp); /* Parse it returning command tree */
if (!cmdp) return NULL; /* If syntax error, error */
bp->mode = save_mode;
/* If a newscmd structure was returned, add it to the cmd tree. */
GETMAIN(treep, struct cmdtree, 1, "DO command tree");
if (!treep) {
bp->input_errors++;
return NULL;
}
treep->next = NULL;
treep->cmd = cmdp;
return treep;
}
/****** Get keyword. *************************************************/
static Bool
get_keyword(np,bp,key)
Rstruc nncb *np;
Rstruc batch *bp;
char *key;
{
struct token *tp;
if ((tp = PEEK()) && tp->type == WORD_TOKEN && EQUAL(tp->string,key)) {
EAT();
return TRUE;
}
else return FALSE;
}
/****** Get a DO-END command group. **********************************/
struct cmdtree *
NNMbgdo(np,bp,mode)
Rstruc nncb *np;
Rstruc batch *bp;
enum batchmode mode;
{
/* Look for DO (required). When found, get commands until END seen.*/
if (get_keyword(np,bp,"DO")) {
NNMbtras(np,bp,"DO");
return get_multiple_commands(np,bp,mode);
}
else return get_single_command(np,bp,mode);
}
./ ADD NAME=NNMBGEXP,SSI=01000030
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BGEXP")
#pragma csect(static,"NN$BGEXP")
#include "nn.h"
#include "nnbatch.h"
static Exp get_exp();
static Choice get_choice();
static Relation get_relation();
static Value get_value();
static Quantity get_quantity();
static Term get_term();
static Factor get_factor();
static Unop get_unop();
static Addop get_addop();
static Mulop get_mulop();
static Logop get_logop();
static Relop get_relop();
static Constant get_constant();
static Variable get_variable();
static Number get_number();
static String get_string();
static Flag get_flag();
static Exp make_exp();
static Choice make_choice();
static Relation make_relation();
static Value make_value();
static Quantity make_quantity();
static Term make_term();
static Factor make_factor();
static Unop make_unop();
static Addop make_addop();
static Mulop make_mulop();
static Logop make_logop();
static Relop make_relop();
static Constant make_constant();
static Variable make_variable();
static Number make_number();
static String make_string();
static Flag make_flag();
/*-------------------------------------------------------------------*/
static Bool
is_reserved(bp,var)
Rstruc batch *bp;
char *var;
{
char *cp;
int varlen = strlen(var);
char vartest[MAX_RESERVED_WORD_LENGTH];
if (varlen >= MIN_RESERVED_WORD_LENGTH
&& varlen <= MAX_RESERVED_WORD_LENGTH) {
memset(vartest,' ',MAX_RESERVED_WORD_LENGTH);
memcpy(vartest,var,varlen);
for (cp = bp->reserved_words; *cp != ' '; cp += 10) {
if (memcmp(vartest,cp,MAX_RESERVED_WORD_LENGTH) == 0) {
return TRUE;
}
}
}
return FALSE;
}
/*-------------------------------------------------------------------*/
static Flag
make_flag(np,bp,type,v)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Fool v;
{
Flag p;
ALLOC(p,flag);
p->s = type;
p->flag1 = v;
return p;
}
/*-------------------------------------------------------------------*/
static String
make_string(np,bp,type,v)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
char *v;
{
String p;
ALLOC(p,string);
p->s = type;
p->string1 = NNMcopy(np,v);
return p;
}
/*-------------------------------------------------------------------*/
static Number
make_number(np,bp,type,v)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
int v;
{
Number p;
ALLOC(p,number);
p->s = type;
p->number1 = v;
return p;
}
/*-------------------------------------------------------------------*/
static Variable
make_variable(np,bp,type,v)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
char *v;
{
Variable p;
ALLOC(p,variable);
p->s = type;
p->variable1 = NNMcopy(np,v);
return p;
}
/*-------------------------------------------------------------------*/
static Relop
make_relop(np,bp,t)
Rstruc nncb *np;
Rstruc batch *bp;
enum optype t;
{
Relop p;
ALLOC(p,relop);
p->op1 = t;
return p;
}
/*-------------------------------------------------------------------*/
static Logop
make_logop(np,bp,t)
Rstruc nncb *np;
Rstruc batch *bp;
enum optype t;
{
Logop p;
ALLOC(p,logop);
p->op1 = t;
return p;
}
/*-------------------------------------------------------------------*/
static Mulop
make_mulop(np,bp,t)
Rstruc nncb *np;
Rstruc batch *bp;
enum optype t;
{
Mulop p;
ALLOC(p,mulop);
p->op1 = t;
return p;
}
/*-------------------------------------------------------------------*/
static Addop
make_addop(np,bp,t)
Rstruc nncb *np;
Rstruc batch *bp;
enum optype t;
{
Addop p;
ALLOC(p,addop);
p->op1 = t;
return p;
}
/*-------------------------------------------------------------------*/
static Unop
make_unop(np,bp,t)
Rstruc nncb *np;
Rstruc batch *bp;
enum optype t;
{
Unop p;
ALLOC(p,unop);
p->op1 = t;
return p;
}
/*-------------------------------------------------------------------*/
static Constant
make_constant_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Number p1;
{
Constant p;
ALLOC(p,constant);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.number1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Constant
make_constant_b(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
String p1;
{
Constant p;
ALLOC(p,constant);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.string1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Constant
make_constant_c(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Flag p1;
{
Constant p;
ALLOC(p,constant);
p->r = RHSTYPE_C;
p->s = type;
p->u.c.flag1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Factor
make_factor_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Constant p1;
{
Factor p;
ALLOC(p,factor);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.constant1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Factor
make_factor_b(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Variable p1;
{
Factor p;
ALLOC(p,factor);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.variable1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Factor
make_factor_c(np,bp,type,p1,p2)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Unop p1;
Factor p2;
{
Factor p;
ALLOC(p,factor);
p->r = RHSTYPE_C;
p->s = type;
p->u.c.unop1 = p1;
p->u.c.factor2 = p2;
return p;
}
/*-------------------------------------------------------------------*/
static Factor
make_factor_d(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Exp p1;
{
Factor p;
ALLOC(p,factor);
p->r = RHSTYPE_D;
p->s = type;
p->u.d.exp1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Term
make_term_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Factor p1;
{
Term p;
ALLOC(p,term);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.factor1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Term
make_term_b(np,bp,type,p1,p2,p3)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Term p1;
Mulop p2;
Factor p3;
{
Term p;
ALLOC(p,term);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.term1 = p1;
p->u.b.mulop2 = p2;
p->u.b.factor3 = p3;
return p;
}
/*-------------------------------------------------------------------*/
static Quantity
make_quantity_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Term p1;
{
Quantity p;
ALLOC(p,quantity);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.term1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Quantity
make_quantity_b(np,bp,type,p1,p2,p3)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Quantity p1;
Addop p2;
Term p3;
{
Quantity p;
ALLOC(p,quantity);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.quantity1 = p1;
p->u.b.addop2 = p2;
p->u.b.term3 = p3;
return p;
}
/*-------------------------------------------------------------------*/
static Value
make_value_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Quantity p1;
{
Value p;
ALLOC(p,value);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.quantity1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Value
make_value_b(np,bp,type,p1,p2)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Value p1;
Quantity p2;
{
Value p;
ALLOC(p,value);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.value1 = p1;
p->u.b.quantity2 = p2;
return p;
}
/*-------------------------------------------------------------------*/
static Relation
make_relation_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Value p1;
{
Relation p;
ALLOC(p,relation);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.value1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Relation
make_relation_b(np,bp,type,p1,p2,p3)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Value p1;
Relop p2;
Value p3;
{
Relation p;
ALLOC(p,relation);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.value1 = p1;
p->u.b.relop2 = p2;
p->u.b.value3 = p3;
return p;
}
/*-------------------------------------------------------------------*/
static Choice
make_choice_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Relation p1;
{
Choice p;
ALLOC(p,choice);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.relation1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Choice
make_choice_b(np,bp,type,p1,p2,p3)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Choice p1;
Logop p2;
Relation p3;
{
Choice p;
ALLOC(p,choice);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.choice1 = p1;
p->u.b.logop2 = p2;
p->u.b.relation3 = p3;
return p;
}
/*-------------------------------------------------------------------*/
static Exp
make_exp_a(np,bp,type,p1)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Choice p1;
{
Exp p;
ALLOC(p,exp);
p->r = RHSTYPE_A;
p->s = type;
p->u.a.choice1 = p1;
return p;
}
/*-------------------------------------------------------------------*/
static Exp
make_exp_b(np,bp,type,p1,p2,p3)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
Exp p1;
Exp p2;
Exp p3;
{
Exp p;
ALLOC(p,exp);
p->r = RHSTYPE_B;
p->s = type;
p->u.b.exp1 = p1;
p->u.b.exp2 = p2;
p->u.b.exp3 = p3;
return p;
}
/*===================================================================*/
static Flag
get_flag(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case WORD_TOKEN:
if (EQUAL(tp->string,"FALSE") ||
EQUAL(tp->string,"NO" ) ||
EQUAL(tp->string,"OFF" )) {
EAT();
return make_flag(np,bp,FLAG_SYMTYPE,FALSE);
}
else
if (EQUAL(tp->string,"TRUE" ) ||
EQUAL(tp->string,"YES" ) ||
EQUAL(tp->string,"ON" )) {
EAT();
return make_flag(np,bp,FLAG_SYMTYPE,TRUE);
}
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static String
get_string(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case STRING_TOKEN:
EAT();
return make_string(np,bp,STRING_SYMTYPE,tp->string);
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Number
get_number(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case NUMBER_TOKEN:
EAT();
return make_number(np,bp,NUMBER_SYMTYPE,tp->number);
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Variable
get_variable(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
enum symtype type;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case WORD_TOKEN:
if (is_reserved(bp,tp->string)) return NULL;
EAT();
type = (enum symtype)NNMbvget(np,bp,tp->string,NO_SYMTYPE);
if (type == NO_SYMTYPE) ERR("variable not declared");
return make_variable(np,bp,type,tp->string);
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Constant
get_constant(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Number a1;
String b1;
Flag c1;
if ((a1 = get_number(np,bp)))
return make_constant_a(np,bp,NUMBER_SYMTYPE,a1);
if ((b1 = get_string(np,bp)))
return make_constant_b(np,bp,STRING_SYMTYPE,b1);
if ((c1 = get_flag(np,bp)))
return make_constant_c(np,bp,FLAG_SYMTYPE,c1);
return NULL;
}
/*-------------------------------------------------------------------*/
static Addop
get_addop(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case PLUS_TOKEN: EAT(); return make_addop(np,bp,ADD_OP);
case MINUS_TOKEN: EAT(); return make_addop(np,bp,SUB_OP);
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Mulop
get_mulop(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case TIMES_TOKEN: EAT(); return make_mulop(np,bp,MUL_OP);
case OVER_TOKEN: EAT(); return make_mulop(np,bp,DIV_OP);
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Logop
get_logop(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case AND_TOKEN: EAT(); return make_logop(np,bp,AND_OP);
case OR_TOKEN: EAT(); return make_logop(np,bp,OR_OP);
case WORD_TOKEN:
if (EQUAL(tp->string,"AND")) {
EAT();
return make_logop(np,bp,AND_OP);
}
if (EQUAL(tp->string,"OR")) {
EAT();
return make_logop(np,bp,OR_OP);
}
return NULL;
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Relop
get_relop(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case EQ_TOKEN: EAT(); return make_relop(np,bp,EQ_OP);
case NE_TOKEN: EAT(); return make_relop(np,bp,NE_OP);
case GT_TOKEN: EAT(); return make_relop(np,bp,GT_OP);
case LT_TOKEN: EAT(); return make_relop(np,bp,LT_OP);
case GE_TOKEN: EAT(); return make_relop(np,bp,GE_OP);
case LE_TOKEN: EAT(); return make_relop(np,bp,LE_OP);
case WORD_TOKEN:
if (EQUAL(tp->string,"IN")) {EAT();
return make_relop(np,bp,IN_OP);}
if (EQUAL(tp->string,"EQ")) {EAT();
return make_relop(np,bp,EQ_OP);}
if (EQUAL(tp->string,"NE")) {EAT();
return make_relop(np,bp,NE_OP);}
if (EQUAL(tp->string,"GT")) {EAT();
return make_relop(np,bp,GT_OP);}
if (EQUAL(tp->string,"LT")) {EAT();
return make_relop(np,bp,LT_OP);}
if (EQUAL(tp->string,"GE")) {EAT();
return make_relop(np,bp,GE_OP);}
if (EQUAL(tp->string,"LE")) {EAT();
return make_relop(np,bp,LE_OP);}
return NULL;
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Unop
get_unop(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case MINUS_TOKEN: EAT(); return make_unop(np,bp,SUB_OP);
case PLUS_TOKEN: EAT(); return make_unop(np,bp,ADD_OP);
case NOT_TOKEN: EAT(); return make_unop(np,bp,NOT_OP);
case WORD_TOKEN:
if (EQUAL(tp->string,"NOT")) {EAT();
return make_unop(np,bp,NOT_OP);}
return NULL;
default: return NULL;
}
}
/*-------------------------------------------------------------------*/
static Bool
get_word(np,bp,word)
Rstruc nncb *np;
Rstruc batch *bp;
char *word;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case WORD_TOKEN:
if (EQUAL(tp->string,word)) {EAT(); return TRUE;}
else return FALSE;
default: return FALSE;
}
}
/*-------------------------------------------------------------------*/
static Bool
get_lpar(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case LPAR_TOKEN: EAT(); return TRUE;
default: return FALSE;
}
}
/*-------------------------------------------------------------------*/
static Bool
get_rpar(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
if (!(tp = PEEK())) LOSE;
switch (tp->type) {
case RPAR_TOKEN: EAT(); return TRUE;
default: return FALSE;
}
}
/*-------------------------------------------------------------------*/
static Factor
get_factor(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Constant a1;
Variable b1;
Unop c1;
Factor c2;
Exp d1;
enum symtype type;
enum symtype type2;
/* a: factor -> constant */
if (a1 = get_constant(np,bp)) {
type = a1->s;
return make_factor_a(np,bp,type,a1);
}
/* b: factor -> variable */
if ((b1 = get_variable(np,bp))) {
type = b1->s;
return make_factor_b(np,bp,type,b1);
}
/* c: factor -> unop factor */
if ((c1 = get_unop(np,bp))) {
if (!(c2 = get_factor(np,bp))) ERR("expecting factor");
type2 = c2->s;
switch (c1->op1) {
case SUB_OP:
if (type2 != NUMBER_SYMTYPE) ERR("not number expression");
type = NUMBER_SYMTYPE;
break;
case ADD_OP:
if (type2 != NUMBER_SYMTYPE) ERR("not number expression");
type = NUMBER_SYMTYPE;
break;
case NOT_OP:
if (type2 != FLAG_SYMTYPE) ERR("not flag expression");
type = FLAG_SYMTYPE;
break;
}
return make_factor_c(np,bp,type2,c1,c2);
}
/* d: factor -> "(" exp ")" */
if (get_lpar(np,bp)) {
if (!(d1 = get_exp(np,bp))) ERR("expecting numeric expression");
if (!get_rpar(np,bp)) ERR("expecting right parenthesis");
type = d1->s;
return make_factor_d(np,bp,type,d1);
}
return NULL;
}
/*-------------------------------------------------------------------*/
static Term
get_term(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Term p;
Factor a1;
Mulop b2;
Factor b3;
enum symtype type;
enum symtype type1;
enum symtype type3;
/* a: term -> factor */
if (!(a1 = get_factor(np,bp))) return NULL;
type = a1->s;
p = make_term_a(np,bp,type,a1);
/* b: term -> term mulop factor */
for (;;) {
if (!(b2 = get_mulop(np,bp))) break;
if (!(b3 = get_factor(np,bp))) ERR("expecting numeric factor");
type1 = p->s;
type3 = b3->s;
if (type1!=NUMBER_SYMTYPE) ERR("operand 1 not number expression");
if (type3!=NUMBER_SYMTYPE) ERR("operand 2 not number expression");
type = NUMBER_SYMTYPE;
p = make_term_b(np,bp,type,p,b2,b3);
}
return p;
}
/*-------------------------------------------------------------------*/
static Quantity
get_quantity(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Quantity p;
Term a1;
Addop b2;
Term b3;
enum symtype type;
enum symtype type1;
enum symtype type3;
/* a: quantity -> term */
if (!(a1 = get_term(np,bp))) return NULL;
type = a1->s;
p = make_quantity_a(np,bp,type,a1);
/* b: quantity -> quantity addop term */
for (;;) {
if (!(b2 = get_addop(np,bp))) break;
if (!(b3 = get_term(np,bp))) ERR("expecting numeric term");
type1 = p->s;
type3 = b3->s;
if (type1!=NUMBER_SYMTYPE) ERR("operand 1 not number expression");
if (type3!=NUMBER_SYMTYPE) ERR("operand 2 not number expression");
type = NUMBER_SYMTYPE;
p = make_quantity_b(np,bp,type,p,b2,b3);
}
return p;
}
/*-------------------------------------------------------------------*/
static Value
get_value(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Value p;
Quantity a1;
Quantity b2;
enum symtype type;
enum symtype type1;
enum symtype type2;
/* a: value -> quantity */
if (!(a1 = get_quantity(np,bp))) return NULL;
type = a1->s;
p = make_value_a(np,bp,type,a1);
/* b: value -> value quantity */
for (;;) {
if (!(b2 = get_quantity(np,bp))) break;
type1 = p->s;
type2 = p->s;
type = STRING_SYMTYPE;
p = make_value_b(np,bp,type,p,b2);
}
return p;
}
/*-------------------------------------------------------------------*/
static Relation
get_relation(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Relation p;
Value a1;
Relop b2;
Value b3;
enum symtype type;
enum symtype type1;
enum symtype type3;
/* a: relation -> value */
if (!(a1 = get_value(np,bp))) return NULL;
type = a1->s;
p = make_relation_a(np,bp,type,a1);
/* b: relation -> value relop value */
if (!(b2 = get_relop(np,bp))) return p;
if (!(b3 = get_value(np,bp)))
ERR("expecting string or numeric value");
type1 = a1->s;
type3 = b3->s;
switch (b2->op1) {
case IN_OP:
if (type1 != STRING_SYMTYPE)
ERR("operand 1 not string expression");
if (type3 != STRING_SYMTYPE)
ERR("operand 3 not string expression");
break;
case EQ_OP:
case NE_OP:
if (!((type1 == NUMBER_SYMTYPE && type3 == NUMBER_SYMTYPE)
|| (type1 == STRING_SYMTYPE && type3 == STRING_SYMTYPE)
|| (type1 == FLAG_SYMTYPE && type3 == FLAG_SYMTYPE)))
ERR("operands are not both of the same type");
break;
default:
if (!((type1 == NUMBER_SYMTYPE && type3 == NUMBER_SYMTYPE)
|| (type1 == STRING_SYMTYPE && type3 == STRING_SYMTYPE)))
ERR("operands are not both numeric or both string expressions");
break;
}
type = FLAG_SYMTYPE;
p = make_relation_b(np,bp,type,a1,b2,b3);
return p;
}
/*-------------------------------------------------------------------*/
static Choice
get_choice(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Choice p;
Relation a1;
Logop b2;
Relation b3;
enum symtype type;
enum symtype type1;
enum symtype type3;
/* a: choice -> relation */
if (!(a1 = get_relation(np,bp))) return NULL;
type = a1->s;
p = make_choice_a(np,bp,type,a1);
/* b: choice -> choice logop relation */
for (;;) {
if (!(b2 = get_logop(np,bp))) break;
if (!(b3 = get_relation(np,bp)))
ERR("expecting logical expression");
type1 = p->s;
type3 = b3->s;
if (type1 != FLAG_SYMTYPE) ERR("operand 1 not logical expression");
if (type3 != FLAG_SYMTYPE) ERR("operand 2 not logical expression");
type = FLAG_SYMTYPE;
p = make_choice_b(np,bp,type,p,b2,b3);
}
return p;
}
/*-------------------------------------------------------------------*/
static Exp
get_exp(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Choice a1;
Exp b1;
Exp b2;
Exp b3;
enum symtype type;
enum symtype type1;
enum symtype type2;
enum symtype type3;
/* b: exp -> "IF" exp "THEN" exp "ELSE" exp */
if (get_word(np,bp,"IF")) {
if (!(b1 = get_exp(np,bp))) ERR("expecting expression");
if (!(get_word(np,bp,"THEN"))) ERR("expecting THEN");
if (!(b2 = get_exp(np,bp))) ERR("expecting expression");
if (!(get_word(np,bp,"ELSE"))) ERR("expecting ELSE");
if (!(b3 = get_exp(np,bp))) ERR("expecting expression");
type1 = b1->s;
type2 = b2->s;
type3 = b3->s;
if (type1 != FLAG_SYMTYPE) ERR("operand 1 not logical expression");
type = type2;
return make_exp_b(np,bp,type,b1,b2,b3);
}
/* a: exp -> choice */
if (!(a1 = get_choice(np,bp))) ERR("expecting IF or expression");
type = a1->s;
return make_exp_a(np,bp,type,a1);
}
/*-------------------------------------------------------------------*/
static Exp
get_strtree(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Exp p;
p = get_exp(np,bp);
if (!p) {
NNMbsynt(np,bp,NULL,0,"no expression found");
return NULL;
}
return p;
}
/*-------------------------------------------------------------------*/
static Exp
get_numtree(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Exp p;
p = get_exp(np,bp);
if (!p) {
NNMbsynt(np,bp,NULL,0,"no expression found");
return NULL;
}
switch (p->s) {
case STRING_SYMTYPE:
NNMbsynt(np,bp,NULL,0,"numeric expression required");
return NULL;
case NUMBER_SYMTYPE:
case FLAG_SYMTYPE:
default: return p;
}
}
/*-------------------------------------------------------------------*/
static Exp
get_flagtree(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
Exp p;
p = get_exp(np,bp);
if (!p) {
NNMbsynt(np,bp,NULL,0,"no expression found");
return NULL;
}
switch (p->s) {
case FLAG_SYMTYPE: return p;
default:
NNMbsynt(np,bp,NULL,0,"logical expression required");
return NULL;
}
}
/****** Get expression and build an expression tree. *****************/
struct ptree *
NNMbgexp(np,bp,type)
Rstruc nncb *np;
Rstruc batch *bp;
enum symtype type;
{
struct ptree *treep = NULL;
/* Define return point for syntax errors during parse. */
switch (setjmp(bp->jump)) {
case ERROR_NONE:
break;
case ERROR_GETMAIN_FAILURE:
NNMbsynt(np,bp,NULL,0,"Not enough memory to parse expression");
return NULL;
default:
bp->syntax_error = TRUE;
return NULL;
}
switch (type) {
case STRING_SYMTYPE:
GETMAIN(treep,struct ptree,1,"string ptree");
if (treep) {
treep->type = STRING_TREETYPE;
treep->exp1 = get_strtree(np,bp);
}
break;
case NUMBER_SYMTYPE:
GETMAIN(treep,struct ptree,1,"number ptree");
if (treep) {
treep->type = NUMBER_TREETYPE;
treep->exp1 = get_numtree(np,bp);
}
break;
case FLAG_SYMTYPE:
GETMAIN(treep,struct ptree,1,"flag ptree");
if (treep) {
treep->type = FLAG_TREETYPE;
treep->exp1 = get_flagtree(np,bp);
}
break;
default: NNMbsynt(np,bp,NULL,0,"Invalid type passed to NNMbgexp");
return NULL;
}
if (!treep) {
NNMbsynt(np,bp,NULL,0,"No storage available to build expression");
return NULL;
}
return treep;
}
./ ADD NAME=NNMBGTOK,SSI=01000046
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BGTOK")
#pragma csect(static,"NN$BGTOK")
#include "nn.h"
#include "nnbatch.h"
/****** Get input line. **********************************************/
static char *
get_input_line(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
char *cp;
for (;;) {
cp = fgets(bp->inline, sizeof(bp->inline), np->batch_infile);
if (!cp) {
if (ferror(np->batch_infile)) {
fprintf(stderr,"\n*** Error reading batch input file ***\n");
abort();
}
bp->eof = TRUE;
return NULL;
}
else if ((cp=strchr(cp,'\n'))) *cp = '\0';
/* Hack to allow standard entry of EOF from the terminal. */
if (EQUAL(bp->inline,"/*")) {
fprintf(np->batch_outfile, "EOF (/*) signalled in input.\n");
bp->eof = TRUE;
return NULL;
}
fprintf(np->batch_outfile, "%s\n", bp->inline);
if (bp->inline[0] != '#') break;
}
return bp->inline;
}
/****** Show token, for debugging only. ******************************/
static char *
token_description(tokp)
struct token *tokp;
{
char *c;
switch (tokp->type) {
case NO_TOKEN: c = "no token"; break;
case EOL_TOKEN: c = "EOL"; break;
case EOF_TOKEN: c = "EOF"; break;
case AND_TOKEN: c = "AND"; break;
case OR_TOKEN: c = "OR"; break;
case NOT_TOKEN: c = "NOT"; break;
case GT_TOKEN: c = "GT"; break;
case LT_TOKEN: c = "LT"; break;
case EQ_TOKEN: c = "EQ"; break;
case NE_TOKEN: c = "NE"; break;
case GE_TOKEN: c = "GE"; break;
case LE_TOKEN: c = "LE"; break;
case LPAR_TOKEN: c = "LPAR"; break;
case RPAR_TOKEN: c = "RPAR"; break;
case PLUS_TOKEN: c = "PLUS"; break;
case MINUS_TOKEN: c = "MINUS"; break;
case TIMES_TOKEN: c = "TIMES"; break;
case OVER_TOKEN: c = "OVER"; break;
case SEMI_TOKEN: c = "SEMI"; break;
case WORD_TOKEN: c = "WORD"; break;
case NUMBER_TOKEN: c = "NUMBER"; break;
case STRING_TOKEN: c = "STRING"; break;
case ERROR_TOKEN: c = "ERROR"; break;
default: c = "?"; break;
}
return c;
}
/****** Get token. ***************************************************/
static Bool
get_token(np,bp,tokp,flushing)
Rstruc nncb *np;
Rstruc batch *bp;
struct token *tokp;
Fool flushing;
{
char *cp;
char *dp;
char *ep;
int len;
Bool inquote;
Bool badtoken;
/* If reached end of current line, get a line */
do {
while (*bp->inchar == '\0') {
if (bp->stop_at_newline) {
tokp->type = EOL_TOKEN;
strcpy(tokp->string,"<**End Of Line**>");
return TRUE;
}
bp->inchar = get_input_line(np,bp);
if (bp->inchar == NULL) {
tokp->type = EOF_TOKEN;
strcpy(tokp->string,"<**End Of File**>");
return TRUE;
}
}
while (isspace(*bp->inchar)) bp->inchar++;
if (*bp->inchar == '#') *bp->inchar = '\0';
} while (*bp->inchar == '\0');
memset(tokp->string, 0, sizeof(tokp->string));
tokp->number = 0;
bp->syntax_error = FALSE;
badtoken = FALSE;
cp = bp->inchar;
if (isdigit(*cp)) {
ep = cp + strspn(cp,"0123456789");
len = ep - cp;
bp->inchar = ep;
if (len > 10) {
badtoken = TRUE;
if (flushing) tokp->type = ERROR_TOKEN;
else NNMbsynt(np,bp,cp,len,"Number too long");
}
else {
tokp->type = NUMBER_TOKEN;
memcpy(tokp->string, cp, len);
tokp->number = atoi(tokp->string);
}
}
else if (isalpha(*cp)) {
dp = tokp->string;
ep = dp + sizeof(tokp->string) - 1;
while (isalnum(*cp)) {
if (dp > ep) {
if (!badtoken) {
badtoken = TRUE;
if (flushing) tokp->type = ERROR_TOKEN;
else NNMbsynt(np,bp,cp,ep-cp, "Word too long");
}
}
else {
*(dp++) = toupper(*(cp++));
}
}
*dp = '\0';
bp->inchar = cp;
tokp->type = badtoken ? ERROR_TOKEN : WORD_TOKEN;
}
else if (*cp == '"') {
bp->inchar++;
cp = bp->inchar;
dp = tokp->string;
ep = tokp->string + sizeof(tokp->string) - 1;
inquote = TRUE;
while (inquote) {
switch (*cp) {
case '\0': NNMbsynt(np,bp,NULL,0,"Missing end quote");
inquote = FALSE;
bp->inchar = cp;
break;
case '"' : inquote = FALSE;
bp->inchar = cp+1;
break;
case '\\': cp++;
/* fall through */
default : if (dp > ep) {
if (!badtoken) {
badtoken = TRUE;
if (flushing) tokp->type = ERROR_TOKEN;
else
NNMbsynt(np,bp,NULL,0,"Quoted string too long");
}
}
else *(dp++) = *(cp++);
break;
}
}
*dp = '\0';
tokp->type = badtoken ? ERROR_TOKEN : STRING_TOKEN;
}
else {
switch (*cp) {
case ';': bp->inchar++; tokp->type = SEMI_TOKEN; break;
case '(': bp->inchar++; tokp->type = LPAR_TOKEN; break;
case ')': bp->inchar++; tokp->type = RPAR_TOKEN; break;
case '+': bp->inchar++; tokp->type = PLUS_TOKEN; break;
case '-': bp->inchar++; tokp->type = MINUS_TOKEN; break;
case '*': bp->inchar++; tokp->type = TIMES_TOKEN; break;
case '/': bp->inchar++; tokp->type = OVER_TOKEN; break;
case '&': bp->inchar++; tokp->type = AND_TOKEN; break;
case '|': bp->inchar++; tokp->type = OR_TOKEN; break;
case '>': bp->inchar++;
switch (*bp->inchar) {
case '=': bp->inchar++; tokp->type = GE_TOKEN; break;
default: tokp->type = GT_TOKEN; break;
}
break;
case '<': bp->inchar++;
switch (*bp->inchar) {
case '=': bp->inchar++; tokp->type = LE_TOKEN; break;
case '>': bp->inchar++; tokp->type = NE_TOKEN; break;
default: tokp->type = LT_TOKEN; break;
}
break;
case '=': bp->inchar++;
switch (*bp->inchar) {
case '=': bp->inchar++; tokp->type = EQ_TOKEN; break;
default: tokp->type = EQ_TOKEN; break;
}
break;
case '^':
case '!': bp->inchar++;
switch (*bp->inchar) {
case '=': bp->inchar++; tokp->type = NE_TOKEN; break;
case '<': bp->inchar++; tokp->type = GT_TOKEN; break;
case '>': bp->inchar++; tokp->type = LT_TOKEN; break;
default: tokp->type = NOT_TOKEN; break;
}
break;
default: if (flushing) tokp->type = ERROR_TOKEN;
else NNMbsynt(np,bp,cp,1,
"Invalid character, cannot scan");
bp->inchar++;
break;
}
memcpy(tokp->string, cp, bp->inchar - cp); /* just in case */
}
if (np->debug_file) {
fprintf(np->debug_file,"token = %s", token_description(tokp));
switch (tokp->type) {
case NUMBER_TOKEN:
fprintf(np->debug_file, "(%d,'%s')\n",
tokp->number, tokp->string);
break;
case WORD_TOKEN:
case STRING_TOKEN:
default:
fprintf(np->debug_file, "(%s)\n", tokp->string);
break;
}
}
return TRUE;
}
/****** Get token. ***************************************************/
Bool
NNMbgtok(np,bp,func)
Rstruc nncb *np;
Rstruc batch *bp;
enum tokenfunc func;
{
if (!bp->tokens_read) {
bp->inchar = get_input_line(np,bp);
bp->tokens_read = TRUE;
if (bp->inchar == NULL) { /* no input at all? */
bp->curtok.type = EOF_TOKEN;
bp->nextok.type = EOF_TOKEN;
return TRUE;
}
}
if (bp->curtok.type == EOF_TOKEN) {
NNMbsynt(np,bp,NULL,0, "Attempt to read token past end of file");
return FALSE;
}
switch (func) {
case TOKEN_PEEK:
if (bp->nextok.type == NO_TOKEN) {
return get_token(np,bp,&bp->nextok,FALSE);
}
else { /* token already peeked at */
return TRUE;
}
case TOKEN_READ:
if (bp->nextok.type == NO_TOKEN) {
return get_token(np,bp,&bp->curtok,FALSE);
}
else { /* token already peeked at */
memcpy((char *)&bp->curtok,
(char *)&bp->nextok,
sizeof(struct token));
bp->nextok.type = NO_TOKEN;
return TRUE;
}
case TOKEN_FLUSH:
if (bp->nextok.type == NO_TOKEN) {
return get_token(np,bp,&bp->curtok,TRUE);
}
else { /* token already peeked at */
memcpy((char *)&bp->curtok,
(char *)&bp->nextok,
sizeof(struct token));
bp->nextok.type = NO_TOKEN;
return TRUE;
}
}
}
./ ADD NAME=NNMBPDEC,SSI=01000059
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: DECLARE
*
* Syntax: DECLARE variablename {STRING | NUMBER | FLAG}
*
* Mode: any
*
* Function: Declares a variable that can be referenced later.
* Its type is specified as well. The type can be:
*
* * STRING - character string
* * NUMBER - integer
* * FLAG - 1 or 0, TRUE or FALSE, ON or OFF, YES or NO
*
* Note: This command is processed at parse time only. It is not an
* executable command. No matter where it appears in the input
* command environment, it will be processed. The only caveat
* is that a variable must be referenced by DECLARE prior to
* any appearance of it in the input stream.
*
* Examples: DECLARE FOO STRING
* DECLARE BAR NUMBER
* DECLARE BAZ FLAG
*
*====================================================================*/
#pragma csect(code, "NN@BPDEC")
#pragma csect(static,"NN$BPDEC")
#include "nn.h"
#include "nnbatch.h"
/****** Parse batch DECLARE command. ****************************/
struct newscmd *
NNMbpdec(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
char *var;
enum symtype type;
ANYTYPE val;
/* Next token must be variable name. */
(void)NNMbgtok(np,bp,TOKEN_READ); /* get token */
if (bp->curtok.type != WORD_TOKEN) {
NNMbsynt(np,bp,NULL,0, "Expected DECLARE variable name not seen");
NNMbflus(np,bp); /* flush input tokens */
return NULL;
}
var = NNMcopy(np,bp->curtok.string);
/* Next token must be one of the words STRING, NUMBER or FLAG. */
(void)NNMbgtok(np,bp,TOKEN_READ); /* get token */
if (bp->curtok.type != WORD_TOKEN) {
NNMbsynt(np,bp,NULL,0, "Expected DECLARE type name not seen");
NNMbflus(np,bp); /* flush input tokens */
return NULL;
}
if (EQUAL(bp->curtok.string,"STRING")) {
type = STRING_SYMTYPE;
val = (ANYTYPE)"";
}
else if (EQUAL(bp->curtok.string,"NUMBER")) {
type = NUMBER_SYMTYPE;
val = (ANYTYPE)0;
}
else if (EQUAL(bp->curtok.string,"FLAG")) {
type = FLAG_SYMTYPE;
val = (ANYTYPE)0;
}
else {
NNMbsynt(np,bp,bp->curtok.string,0,
"DECLARE type not one of STRING, NUMBER or FLAG");
return NULL;
}
if (!NNMbdecl(np,bp,var,type,val)) {
NNMbsynt(np,bp,var,0, "Declaration failed");
return NULL;
}
return NULL;
}
./ ADD NAME=NNMBPDER,SSI=01000028
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: DEREGISTER
*
* Syntax: DEREGISTER
*
* Mode: per_newsgroup
*
* Function: Deregisters the current newsgroup.
*
* Note: Arguments are not permitted. If they are given, the
* function will not be performed.
*
* Examples: DEREGISTER
*
*====================================================================*/
#pragma csect(code, "NN@BPDER")
#pragma csect(static,"NN$BPDER")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch DEREGISTER command. ****************************/
static void
NNMbxder(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
Rstruc newsgroup *gp = bp->gp;
gp->registered = 0;
fprintf(np->batch_outfile,"Newsgroup %s deregistered.\n",gp->name);
NNMsave(np,NULL); /* Checkpoint NEWSRC file */
return;
}
/****** Parse batch DEREGISTER command. ****************************/
struct newscmd *
NNMbpder(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp;
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"DEREGISTER"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
if (bp->mode != PER_NEWSGROUP_MODE) {
NNMbsynt(np,bp,NULL,0,
"DEREGISTER is invalid outside of per-newsgroup mode");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for DEREGISTER command");
if (cmdp) {
cmdp->mode = PER_NEWSGROUP_MODE;
cmdp->proc = NNMbxder;
}
return cmdp;
}
./ ADD NAME=NNMBPELS,SSI=01000023
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BPELS")
#pragma csect(static,"NN$BPELS")
#include "nn.h"
#include "nnbatch.h"
/****** Parse batch ELSE command. ****************************/
struct newscmd *
NNMbpels(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
struct cmdtree *elsecmds = NULL;
cmdp = bp->ifcmd;
bp->ifcmd = NULL;
if (!cmdp) {
NNMbsynt(np,bp,NULL,0,"ELSE without matching IF found");
}
/* Get DO-END command group. */
elsecmds = NNMbgdo(np,bp,bp->mode);
if (bp->syntax_error) return NULL;
if (cmdp) cmdp->cmd.fcmd.elsecmds = elsecmds;
return NULL; /* cmdp was already returned by IF */
}
./ ADD NAME=NNMBPEXE,SSI=01000051
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: EXEC
*
* Syntax: EXEC {datum}* ;
*
* Mode: any (but see note)
*
* Function: Executes the TSO command built from the specified
* data items. Items can be:
*
* * text strings
* * integers
* * words representing variables that have values
*
* Note: When words are used, the values they represent must be
* valid for the mode in which the EXEC is executed.
*
* Note: Since the command can span input lines and the number of
* arguments is variable, the arguments MUST be terminated
* by a semicolon or end of file.
*
* Examples: EXEC "time";
* EXEC "SE 'I have " UNREAD " new items' USER(JRL)";
*
*====================================================================*/
#pragma csect(code, "NN@BPEXE")
#pragma csect(static,"NN$BPEXE")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch EXEC command. ****************************/
static void
NNMbxexe(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
char *string;
int rc;
string = NNMbbexp(np,bp,cmdp->cmd.mcmd.ptreep,STRING_SYMTYPE);
if (bp->runtime_error) {
fprintf(np->batch_outfile,
"Command not executed due to errors building argument\n");
}
else {
fprintf(np->batch_outfile, "Executing command:\n%s\n\n", string);
rc = NNMtso(string);
fprintf(np->batch_outfile, "\nReturn code: %d\n",rc);
}
return;
}
/****** Parse batch EXEC command. ****************************/
struct newscmd *
NNMbpexe(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
struct ptree *treep = NULL;
treep = NNMbgexp(np,bp,STRING_SYMTYPE); /* Get data string struct */
if (!treep) {
NNMbsynt(np,bp,NULL,0,"Error in arguments to EXEC");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXEC command");
if (cmdp) {
cmdp->mode = ANY_MODE;
cmdp->proc = NNMbxexe;
cmdp->cmd.mcmd.ptreep = treep;
}
return cmdp;
}
./ ADD NAME=NNMBPEXT,SSI=010E0051
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: EXTRACT
*
* Syntax: In per-newsgroup mode: EXTRACT ALL / READ / UNREAD
* In per-article mode: EXTRACT
*
* Mode: per-newsgroup or per-article
*
* Function: EXTRACTs all, read, or unread articles in the current
* newsgroup; extracts the current article.
*
* Note: The file into which the article(s) are extracted is
* specified by the contents of file DD:NNEXTTAB, which
* is a listing of newsgroups and filenames. The filenames
* are expected to contain a wildcard asterisk, which is
* substituted with the article number.
*
* Examples: EXTRACT
* EXTRACT ALL
* EXTRACT READ
* EXTRACT UNREAD
*
*====================================================================*/
#pragma csect(code, "NN@BPEXT")
#pragma csect(static,"NN$BPEXT")
#include "nn.h"
#include "nnbatch.h"
/********** Extract this article. ************************************/
static int
extract_this_article(np,bp,gp,vp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
VARK *vp;
{
Rstruc newsarticle *ap;
FILE *xfp;
char *cp1;
char *cp2;
char ddname [9];
char exdsn [81];
char expds [81];
char member [81];
char thing_to_open [81];
Bool automark;
ap = VARK2PARTICLE(*vp);
*member = '\0';
*ddname = '\0';
if (*bp->extractds_member) {
sprintf(member,"%8.8d",ap->number);
for (cp1=member, cp2=bp->extractds_member;
*cp1=='0' && *cp2;
cp1++, cp2++) {
*cp1 = *cp2;
}
sprintf(exdsn, "%s%s%s", bp->extractds_part1, member,
bp->extractds_part2);
}
else strcpy(exdsn,bp->extractds);
automark = GETB("AUTOMARK");
np->extract_tab_expanding = GETB("TABEXPAND");
np->extract_appending = bp->extractds_mode == PDS
? FALSE
: GETB("APPEND");
np->extract_blank_before_separator = GETB("BLANKSEP");
np->extract_separator_line = GETC("SEPARATOR");
np->extract_write_error = FALSE;
np->extract_close_error = FALSE;
/* Preallocate the data set so that we don't run out of space
* and so that brain-damaged C/370 doesn't barf on hyphens.
* If it already exists, use the existing one.
*/
if (bp->extractds_mode == PDS) {
strcpy(expds,exdsn);
cp1 = strchr(expds,'(');
*cp1 = '\0';
cp2 = strchr(cp1+1,')');
*cp2 = '\0';
strcpy(member,cp1+1);
if (!NNMalloc(expds,ddname,PDS,gp->article_count)) {
fprintf(np->batch_outfile,
"Could not allocate %s for extract.\n",expds);
bp->runtime_error = TRUE;
return 0;
}
sprintf(thing_to_open, "dd:%s(%s)", ddname, member);
sprintf(exdsn, "%s(%s)", expds, member);
}
else {
if (!NNMalloc(exdsn,ddname,SEQ,gp->article_count)) {
fprintf(np->batch_outfile,
"Could not allocate %s for extract.\n",exdsn);
bp->runtime_error = TRUE;
return 0;
}
sprintf(thing_to_open, "dd:%s", ddname);
}
xfp = OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(thing_to_open,
np->extract_appending);
if (!xfp) {
perror(exdsn);
fprintf(np->batch_outfile,"Could not open %s for extract.\n",exdsn);
bp->runtime_error = TRUE;
return 0;
}
if (!NNMpick(np,ap)) { /* Pick article */
fprintf(np->batch_outfile,
"Error accessing article %d of %s.\n",ap->number,gp->name);
fprintf(np->batch_outfile,
"Extraction into %s was not done.\n",exdsn);
bp->runtime_error = TRUE;
}
else {
NNMbtext(np,&ap->thdr,xfp); /* Print text */
}
if (fclose(xfp) < 0) {
fprintf(np->batch_outfile,
"Error closing %s.\n", exdsn);
bp->runtime_error = TRUE;
}
(void)NNMunalc(ddname);
if (bp->runtime_error ||
np->extract_write_error || np->extract_close_error) {
fprintf(np->batch_outfile,
"Error extracting article %d of %s into %s.\n",
ap->number, gp->name, exdsn);
bp->runtime_error = TRUE;
}
else {
if (automark && IsUnread(*vp)) {
NNMmarr(np,gp,vp);
fprintf(np->batch_outfile,
"Article %d of %s extracted into %s and marked read.\n",
ap->number, gp->name, exdsn);
NNMsave(np,NULL); /* Checkpoint NEWSRC file */
}
else {
fprintf(np->batch_outfile,
"Article %d of %s extracted into %s.\n",
ap->number, gp->name, exdsn);
}
}
return (bp->runtime_error ? 0 : 1);
}
/********** Extract articles. ****************************************/
static int
extract_articles(np,bp,gp,extracting)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
enum extracting_mode extracting;
{
VARK *vp;
VARK *vpfirst;
VARK *vplast;
int count;
np->current_newsgroup = gp;
np->newsgroup_selected = FALSE;
np->show_all_articles = TRUE;
if (!GroupSelected(gp)) gp = NNMdng(np,gp,NULL);
if (!gp) return 0;
bp->gp = gp;
count = 0;
if (gp->article_vector) {
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
int Number = VARK2NUMBER(gp,vp);
if ((extracting == EXTRACTING_ALL)
|| (extracting == EXTRACTING_READ && IsRead(*vp))
|| (extracting == EXTRACTING_UNREAD && IsUnread(*vp))) {
if (NNMrarh(np,gp,vp,0,NULL)) { /* retrieve article hdr */
count += extract_this_article(np,bp,gp,vp);
}
}
}
}
return count;
}
/********** Get extract file. ****************************************/
static Bool
get_extract_file(np,bp,gp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
{
FILE *tabfp;
char *asp;
char *cp;
char *cp1;
char *cp2;
char *lp;
char *rp;
int len;
enum data_set_type mode;
Bool found_extract;
char line [260];
char tabname [260];
char tabds [260];
strcpy(bp->extractds,"");
/* Open the extract table. */
if (!(tabfp = fopen("DD:NNEXTTAB","r"))) {
perror("extract table (ddname NNEXTTAB)");
fprintf(np->batch_outfile,"Could not open extract table.\n");
bp->runtime_error = TRUE;
return FALSE;
}
/* Search the extract table for a line that matches this newsgroup. */
found_extract = FALSE;
do {
fgets(line, sizeof line, tabfp);
if (feof(tabfp)) break;
if (ferror(tabfp)) {
fprintf(np->batch_outfile,
"Error reading extract table (ddname NNEXTTAB)");
break;
}
strcpy(tabname,"");
strcpy(tabds ,"");
sscanf(line,"%s %s",tabname, tabds);
if (!*tabname) continue;
lowercase_in_place(tabname);
if (UNEQUAL(tabname, gp->name)) continue;
found_extract = TRUE;
if (!*tabds) {
fprintf(np->batch_outfile,
"Extract table entry for group %s has no file name specified.\n",
gp->name);
break;
}
} while (!found_extract);
if (!found_extract) {
fprintf(np->batch_outfile,
"Extract terminated for group %s, no entry in extract table.\n",
gp->name);
return FALSE;
}
if (fclose(tabfp) < 0) {
fprintf(stderr,"Error closing extract table (ddname NNEXTTAB)");
fprintf(np->batch_outfile,"Could not close extract table\n");
bp->runtime_error = TRUE;
return FALSE;
}
if (*tabds == '!') {
fprintf(np->batch_outfile,
"Extract suppressed for group %s ('!' in extract table).\n",
gp->name);
return FALSE;
}
/* Copy table dsn to extract dsn, upcasing and stripping all quotes */
for (cp1 = tabds, cp2 = bp->extractds; *cp1; cp1++) {
if (*cp1 != '\'') *cp2++ = toupper(*cp1);
}
*cp2 = '\0';
lp = strchr(bp->extractds,'(');
rp = strchr(bp->extractds,')');
asp = strchr(bp->extractds,'*');
if (lp && rp) {
if (*(rp+1) != '\0') {
fprintf(np->batch_outfile,
"Misuse of parentheses in extract file template %s\n",
bp->extractds);
bp->runtime_error = TRUE;
return FALSE;
}
if (!asp) {
fprintf(np->batch_outfile,
"Parentheses without '*' in extract file template %s\n",
bp->extractds);
fprintf(np->batch_outfile,
"(cannot append multiple articles to same PDS member)\n");
bp->runtime_error = TRUE;
return FALSE;
}
mode = PDS;
}
else {
if (lp || rp) {
fprintf(np->batch_outfile,
"Misuse of parentheses in extract file template %s\n",
bp->extractds);
bp->runtime_error = TRUE;
return FALSE;
}
mode = SEQ;
}
if (strchr(asp+1,'*')) {
fprintf(np->batch_outfile,
"Too many '*' in extract file template %s\n",
bp->extractds);
bp->runtime_error = TRUE;
return FALSE;
}
if (asp) {
switch (*(asp+1)) {
case '\0':
case ')':
case '(':
case '.': break;
default:
fprintf(np->batch_outfile,
"Invalid use of '*' in extract file template %s\n",
bp->extractds);
fprintf(np->batch_outfile,
"(must be followed by '.', ')' or end of name)\n");
bp->runtime_error = TRUE;
return FALSE;
}
for (cp = asp-1;
cp >= bp->extractds && (*cp != '(' && *cp != '.');
cp--);
cp++;
if (cp == asp) {
fprintf(np->batch_outfile,
"Invalid use of '*' in extract file template %s\n",
bp->extractds);
fprintf(np->batch_outfile,
"(must be preceded by an alphanumeric dsname char)\n");
bp->runtime_error = TRUE;
return FALSE;
}
len = cp - bp->extractds;
memcpy(bp->extractds_part1, bp->extractds, len);
*(bp->extractds_part1 + len) = '\0';
len = asp - cp;
memcpy(bp->extractds_member, cp, len);
*(bp->extractds_member + len) = '\0';
strcpy(bp->extractds_part2, asp+1);
}
else {
strcpy(bp->extractds_part1, bp->extractds);
strcpy(bp->extractds_part2, "");
strcpy(bp->extractds_member,"");
}
bp->extractds_mode = mode;
return TRUE;
}
/********** Execute batch EXTRACT command. ***************************/
static void
NNMbxext(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
struct newsgroup *gp = bp->gp;
int count = 0;
enum extracting_mode extracting;
extracting = cmdp->cmd.xcmd.extracting;
if (get_extract_file(np,bp,gp)) {
if (extracting == NO_EXTRACTING_MODE) {
count = extract_this_article(np,bp,gp,bp->vp);
}
else {
count = extract_articles(np,bp,gp,extracting);
}
}
if (bp->runtime_error) {
fprintf(np->batch_outfile, "Extraction failed for %s.\n",
gp->name);
}
else {
fprintf(np->batch_outfile, "%d article%s extracted for %s.\n",
count, count==1 ? "" : "s", gp->name);
}
return;
}
/****** Per-newsgroup mode EXTRACT. **********************************/
static struct newscmd *
parse_newsgroup_extract(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
enum extracting_mode extracting = NO_EXTRACTING_MODE;
/*
* Next token must be ALL, READ or UNREAD.
*/
if (NNMbgtok(np,bp,TOKEN_READ)) { /* get token */
switch (bp->curtok.type) {
case WORD_TOKEN:
if (EQUAL(bp->curtok.string,"ALL")) {
extracting = EXTRACTING_ALL;
}
if (EQUAL(bp->curtok.string,"READ")) {
extracting = EXTRACTING_READ;
}
else if (EQUAL(bp->curtok.string,"UNREAD")) {
extracting = EXTRACTING_UNREAD;
}
break;
default:
break;
}
}
if (extracting == NO_EXTRACTING_MODE) {
NNMbsynt(np,bp,bp->curtok.string,0,
"EXTRACT in per-newsgroup mode requires ALL, READ or UNREAD");
}
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"EXTRACT"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXTRACT command");
if (cmdp) {
cmdp->mode = PER_NEWSGROUP_MODE;
cmdp->proc = NNMbxext;
cmdp->cmd.xcmd.extracting = extracting;
}
return cmdp;
}
/****** Per-article mode EXTRACT. ************************************/
static struct newscmd *
parse_article_extract(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"EXTRACT"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXTRACT command");
if (cmdp) {
cmdp->mode = PER_ARTICLE_MODE;
cmdp->proc = NNMbxext;
cmdp->cmd.xcmd.extracting = NO_EXTRACTING_MODE;
}
return cmdp;
}
/****** Parse batch EXTRACT command. ****************************/
struct newscmd *
NNMbpext(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
switch (bp->mode) {
case PER_NEWSGROUP_MODE: return parse_newsgroup_extract (np,bp);
case PER_ARTICLE_MODE: return parse_article_extract (np,bp);
default:
NNMbsynt(np,bp,NULL,0,
"EXTRACT belongs in per-newsgroup mode or per-article mode");
return NULL;
}
}
./ ADD NAME=NNMBPFOR,SSI=01010010
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: FOR
*
* Syntax: (1) in top-level mode...
*
* FOR criterion {WHEN filter} DO;
* command(s);
* END;
*
* where
*
* criterion is one of: ALL
* REGISTERED
* UNREGISTERED
* * not implemented: "groupmask" (e.g. "comp*")
* * not implemented: {NEWS}GROUP{S} "groupnames"
*
* filter is any flag expression
*
* commands are any commands for the appropriate mode
*
* Examples:
*
* FOR ALL DO ... { per-newsgroup commands }
* FOR REGISTERED DO ...
* FOR ... WHEN (READ = nn) DO ...
* FOR ... WHEN (UNREAD > nn) DO ...
* FOR ... WHEN (COUNT < nn) DO ...
* the following are not implemented:
* FOR "comp.*" DO ...
* FOR GROUPS "a.b.c d.e.f" DO ...
* FOR NEWSGROUP "a.b.c" DO ...
*
* Syntax: (2) in per-newsgroup mode...
*
* FOR criterion {WHEN filter} DO;
* command(s);
* END;
*
* where
*
* criterion is one of: ALL
* READ
* UNREAD
* i TO j (i = number or FIRST,
* (j = number or LAST)
*
* filter is any flag expression
*
* commands are any commands for the appropriate mode
*
* Examples:
*
* FOR ALL WHEN "foo" IN SUBJECT DO ...
* FOR UNREAD DO ...
* FOR FIRST TO 10 DO ...
*
* Mode: (1) top-level (picking newsgroups)
* (2) per-newsgroup (picking articles)
*
* For (1), the commands between DO and END are in per-newsgroup mode.
* For (2), the commands between DO and END are in per-article mode.
*
* Function: Defines operations to be performed on each newsgroup
* in a list of newsgroups (1), or on each article in a
* list of articles (2).
*
*
*====================================================================*/
#pragma csect(code, "NN@BPFOR")
#pragma csect(static,"NN$BPFOR")
#include "nn.h"
#include "nnbatch.h"
/****** Get keyword. *************************************************/
static Bool
get_keyword(np,bp,key)
Rstruc nncb *np;
Rstruc batch *bp;
char *key;
{
struct token *tp;
if ((tp = PEEK()) && tp->type == WORD_TOKEN && EQUAL(tp->string,key)) {
EAT();
return TRUE;
}
else return FALSE;
}
/****** Parse initial-mode FOR for newsgroups. ***********************/
static struct newscmd *
parse_for_newsgroups(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
struct newscmd *cmdp = NULL;
struct ptree *filter = NULL;
struct cmdtree *treep = NULL;
struct ptree *groups = NULL;
enum which_newsgroups which = NO_NEWSGROUPS;
/* Look for criterion, one of:
* ALL
* REGISTERED
* UNREGISTERED
* (not implemented) GROUPMASK group-mask-expression
* {NEWS}GROUP{S} group-name-expression
*/
if ((tp = PEEK())) {
switch (tp->type) {
case WORD_TOKEN:
if (EQUAL(tp->string,"ALL")) {
EAT();
which = ALL_NEWSGROUPS;
}
else if (EQUAL(tp->string,"REGISTERED")) {
EAT();
which = REGISTERED_NEWSGROUPS;
}
else if (EQUAL(tp->string,"UNREGISTERED")) {
EAT();
which = UNREGISTERED_NEWSGROUPS;
}
else if (EQUAL(tp->string,"GROUP")
|| EQUAL(tp->string,"GROUPS")
|| EQUAL(tp->string,"NEWSGROUP")
|| EQUAL(tp->string,"NEWSGROUPS")) {
EAT();
which = NAMED_NEWSGROUPS;
}
else if (EQUAL(tp->string,"GROUPMASK")
|| EQUAL(tp->string,"NEWSGROUPMASK")) {
EAT();
which = MASKED_NEWSGROUPS;
}
break;
case STRING_TOKEN: if (strchr(tp->string,'*'))
which = MASKED_NEWSGROUPS;
else which = NAMED_NEWSGROUPS;
break;
default:
break;
}
}
switch (which) {
case NO_NEWSGROUPS:
NNMbsynt(np,bp,NULL,0,
"Missing FOR criterion - ALL, REGISTERED, UNREGISTERED, NEWSGROUPS");
break;
case NAMED_NEWSGROUPS:
groups = NNMbgexp(np,bp,STRING_SYMTYPE);
if (!groups) NNMbsynt(np,bp,NULL,0,
"No valid group list specified");
break;
case MASKED_NEWSGROUPS:
groups = NNMbgexp(np,bp,STRING_SYMTYPE);
if (!groups) NNMbsynt(np,bp,NULL,0,
"No valid group mask specified");
break;
default: break;
}
/* Look for WHEN. If found, then look for filter, a flag expression.
*/
if (get_keyword(np,bp,"WHEN")) {
filter = NNMbgexp(np,bp,FLAG_SYMTYPE);
if (!filter) {
NNMbsynt(np,bp,NULL,0,"No valid filter expression specified");
}
}
/* Get DO-END command group. */
treep = NNMbgdo(np,bp,PER_NEWSGROUP_MODE);
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for FOR command");
if (cmdp) {
cmdp->mode = INITIAL_MODE;
cmdp->proc = NNMbxfng;
cmdp->cmd.icmd.fors.filter = filter;
cmdp->cmd.icmd.fors.treep = treep;
cmdp->cmd.icmd.fors.crit.which = which;
cmdp->cmd.icmd.fors.crit.groups = groups;
}
return cmdp;
}
/****** Parse per-newsgroup-mode FOR for articles. *******************/
static struct newscmd *
parse_for_articles(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct token *tp;
struct newscmd *cmdp = NULL;
struct ptree *filter = NULL;
struct cmdtree *treep = NULL;
struct ptree *first = NULL;
struct ptree *last = NULL;
enum which_articles which = NO_ARTICLES;
/* Look for criterion, one of:
* ALL
* READ
* UNREAD
* i/FIRST to j/LAST
*
* Note: FIRST and LAST will be variables at run time, making it
* easier to handle them. That way you can say things like
* FIRST + 1 TO LAST - 3.
*/
if ((tp = PEEK())) {
switch (tp->type) {
case WORD_TOKEN:
if (EQUAL(tp->string,"ALL")) {
EAT();
which = ALL_ARTICLES;
}
else if (EQUAL(tp->string,"READ")) {
EAT();
which = READ_ARTICLES;
}
else if (EQUAL(tp->string,"UNREAD")) {
EAT();
which = UNREAD_ARTICLES;
}
else which = RANGED_ARTICLES;
break;
default: which = RANGED_ARTICLES;
break;
}
}
switch (which) {
case NO_ARTICLES:
NNMbsynt(np,bp,NULL,0,
"Missing FOR criterion - ALL, READ, UNREAD, or n/FIRST to n/LAST");
break;
case RANGED_ARTICLES:
first = NNMbgexp(np,bp,NUMBER_SYMTYPE);
if (!first) NNMbsynt(np,bp,NULL,0,
"No valid range start given");
if (get_keyword(np,bp,"TO")) {
last = NNMbgexp(np,bp,NUMBER_SYMTYPE);
if (!last) NNMbsynt(np,bp,NULL,0,
"No valid range end given");
}
else last = NULL;
break;
default: break;
}
/* Look for WHEN. If found, then look for filter, a flag expression.*/
if (get_keyword(np,bp,"WHEN")) {
filter = NNMbgexp(np,bp,FLAG_SYMTYPE);
if (!filter) {
NNMbsynt(np,bp,NULL,0,"No valid filter expression specified");
}
}
/* Get DO-END command group. */
treep = NNMbgdo(np,bp,PER_ARTICLE_MODE);
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for FOR command");
if (cmdp) {
cmdp->mode = PER_NEWSGROUP_MODE;
cmdp->proc = NNMbxfar;
cmdp->cmd.ncmd.fors.filter = filter;
cmdp->cmd.ncmd.fors.treep = treep;
cmdp->cmd.ncmd.fors.crit.which = which;
cmdp->cmd.ncmd.fors.crit.first = first;
cmdp->cmd.ncmd.fors.crit.last = last;
}
return cmdp;
}
/****** Parse batch FOR command. ****************************/
struct newscmd *
NNMbpfor(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
switch (bp->mode) {
case INITIAL_MODE: return parse_for_newsgroups(np,bp);
case PER_NEWSGROUP_MODE: return parse_for_articles (np,bp);
default: NNMbsynt(np,bp,NULL,0,
"FOR belongs in initial mode or per-newsgroup mode");
return NULL;
}
}
./ ADD NAME=NNMBPHEL,SSI=01000013
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: HELP
*
* Syntax: HELP {word}*
*
* Mode: any
*
* Function: Writes help information to the output file.
*
* Note: Words may be specified, but are currently ignored. All
* arguments are flushed until a new line or ';' is seen.
*
* Examples: HELP
* HELP FOR
* HELP "anything" (at all), it doesn't matter!
*
*====================================================================*/
#pragma csect(code, "NN@BPHEL")
#pragma csect(static,"NN$BPHEL")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch HELP command. ****************************/
static void
NNMbxhel(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
FILE *helpfp;
char helpline[257];
if (!(helpfp = fopen("DD:NNBATHLP","r"))) {
perror("ddname NNBATHLP");
fprintf(np->batch_outfile,
"\n\n*** Help not available - cannot open batch help file. ***\n");
return;
}
for (;;) {
fgets(helpline, sizeof(helpline), helpfp);
if (feof(helpfp)) break;
if (ferror(helpfp)) {
fprintf(np->batch_outfile,
"\n\n*** Help terminated - error reading help file. ***\n");
break;
}
fprintf(np->batch_outfile,"%s",helpline);
}
fprintf(np->batch_outfile,"\n");
fclose(helpfp);
return;
}
/****** Parse batch HELP command. ****************************/
struct newscmd *
NNMbphel(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp;
bp->stop_at_newline = TRUE;
while (NNMbgtok(np,bp,TOKEN_READ)) { /* Get token */
switch (bp->curtok.type) {
case EOF_TOKEN:
case EOL_TOKEN:
case SEMI_TOKEN: break;
default: NNMbsynt(np,bp,bp->curtok.string,0,
"Extraneous parameter for HELP");
continue;
}
break;
}
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for HELP command");
if (cmdp) {
cmdp->mode = ANY_MODE;
cmdp->proc = NNMbxhel;
}
return cmdp;
}
./ ADD NAME=NNMBPIF,SSI=01000031
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: IF
*
* Syntax: IF condition THEN DO;
* command(s);
* END;
* ELSE DO;
* command(s);
* END;
*
* where
*
* condition is any flag expression
*
* commands are any commands for the appropriate mode
*
* Examples:
*
* IF AUTOREGISTER THEN DO ...
* IF SERVER != "" THEN DO ...
* IF (A = 1 | B = 2) THEN DO ...
*
* Mode: any (but see note)
*
* The commands between DO and END, for the THEN and ELSE groups,
* must be in the appropriate mode.
*
* Function: If condition is true, executes commands in the first
* command group; otherwise executes commands in the second
* command group.
*
*====================================================================*/
#pragma csect(code, "NN@BPIF ")
#pragma csect(static,"NN$BPIF ")
#include "nn.h"
#include "nnbatch.h"
/****** Execute commands. ********************************************/
static void
execute_commands(np,bp,treep)
Rstruc nncb *np;
Rstruc batch *bp;
struct cmdtree *treep;
{
for (; treep; treep = treep->next) {
bp->runtime_error = FALSE;
(treep->cmd->proc) (np,bp,treep->cmd);
SETB("ERROR",bp->runtime_error);
}
return;
}
/****** Execute batch IF command. ************************************/
static void
NNMbxif(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
struct ptree *condition;
struct cmdtree *thencmds;
struct cmdtree *elsecmds;
Fool condval;
condition = cmdp->cmd.fcmd.condition;
thencmds = cmdp->cmd.fcmd.thencmds;
elsecmds = cmdp->cmd.fcmd.elsecmds;
condval = (Fool) NNMbbexp(np,bp,condition,FLAG_SYMTYPE);
if (bp->runtime_error) return;
if (condval) execute_commands(np,bp,thencmds);
else execute_commands(np,bp,elsecmds);
return;
}
/****** Get keyword. *************************************************/
static Bool
get_keyword(np,bp,key)
Rstruc nncb *np;
Rstruc batch *bp;
char *key;
{
struct token *tp;
if ((tp = PEEK())
&& tp->type == WORD_TOKEN
&& EQUAL(tp->string,key)) {
EAT();
return TRUE;
}
else return FALSE;
}
/****** Parse batch IF command. ****************************/
struct newscmd *
NNMbpif(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
struct ptree *condition = NULL;
struct cmdtree *thencmds = NULL;
/* Look for condition */
condition = NNMbgexp(np,bp,FLAG_SYMTYPE);
if (condition == NULL) {
NNMbsynt(np,bp,NULL,0,"Missing IF condition");
return NULL;
}
/* Look for THEN (required). */
if (!(get_keyword(np,bp,"THEN"))) {
NNMbsynt(np,bp,NULL,0,"Missing THEN keyword");
return NULL;
}
/* Get DO-END command group.
*/
thencmds = NNMbgdo(np,bp,bp->mode);
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for IF command");
if (cmdp) {
cmdp->mode = bp->mode;
cmdp->proc = NNMbxif;
cmdp->cmd.fcmd.condition = condition;
cmdp->cmd.fcmd.thencmds = thencmds;
cmdp->cmd.fcmd.elsecmds = NULL;
}
/* Make sure any following ELSE is properly handled. */
bp->ifcmd = cmdp;
return cmdp;
}
./ ADD NAME=NNMBPLIS,SSI=01020057
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: LIST
*
* Syntax: LIST
*
* Mode: per_article
*
* Function: Lists the contents of the current news article.
*
* Note: Arguments are not permitted. If they are given, the
* function will not be performed.
*
* Examples: LIST
*
*====================================================================*/
#pragma csect(code, "NN@BPLIS")
#pragma csect(static,"NN$BPLIS")
#include "nn.h"
#include "nnbatch.h"
/********** Execute batch LIST command. ******************************/
static void
NNMbxlis(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
Rstruc newsarticle *ap = VARK2PARTICLE(*bp->vp);
NNMpick(np,ap); /* Pick article */
NNMbtext(np,&ap->thdr,NULL); /* Print text */
return;
}
/****** Parse batch LIST command. ************************************/
struct newscmd *
NNMbplis(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp;
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"LIST"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
if (bp->mode != PER_ARTICLE_MODE) {
NNMbsynt(np,bp,NULL,0,"LIST is invalid outside of per-article mode");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for LIST command");
if (cmdp) {
cmdp->mode = PER_ARTICLE_MODE;
cmdp->proc = NNMbxlis;
}
return cmdp;
}
./ ADD NAME=NNMBPMAR,SSI=01030025
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: MARK
*
* Syntax: MARK { READ / UNREAD }
*
* Default: MARK READ
*
* Mode: per-article
*
* Function: Marks the article read or unread.
*
* Examples: MARK
* MARK READ
* MARK UNREAD
*
*====================================================================*/
#pragma csect(code, "NN@BPMAR")
#pragma csect(static,"NN$BPMAR")
#include "nn.h"
#include "nnbatch.h"
/********** Execute batch MARK command. ******************************/
static void
NNMbxmar(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
struct newsgroup *gp = bp->gp;
VARK *vp = bp->vp;
char *what = "not";
switch (cmdp->cmd.rcmd.marking) {
case MARKING_READ: NNMmarr(np,gp,vp);
what = "read";
break;
case MARKING_UNREAD: NNMmaru(np,gp,vp);
what = "unread";
break;
}
fprintf(np->batch_outfile, "Article %d of %s marked %s.\n",
VARK2NUMBER(gp,vp), gp->name, what);
NNMsave(np,NULL); /* Checkpoint NEWSRC file */
return;
}
/****** Parse batch MARK command. ****************************/
struct newscmd *
NNMbpmar(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
enum marking_mode marking = MARKING_READ;
/* Next token, if present, must be READ or UNREAD. */
if (NNMbgtok(np,bp,TOKEN_READ)) { /* get token */
switch (bp->curtok.type) {
case EOL_TOKEN:
case EOF_TOKEN:
case SEMI_TOKEN: marking = MARKING_READ;
break;
case WORD_TOKEN: if (EQUAL(bp->curtok.string,"READ")) {
marking = MARKING_READ;
}
else if (EQUAL(bp->curtok.string,"UNREAD")) {
marking = MARKING_UNREAD;
}
else {
NNMbsynt(np,bp,bp->curtok.string,0,
"MARK operand must be READ or UNREAD");
}
break;
default: NNMbsynt(np,bp,bp->curtok.string,0,
"MARK operand must be READ or UNREAD");
break;
}
}
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"MARK"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
if (bp->mode != PER_ARTICLE_MODE) {
NNMbsynt(np,bp,NULL,0,"MARK is invalid outside of per-article mode");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for MARK command");
if (cmdp) {
cmdp->mode = PER_ARTICLE_MODE;
cmdp->proc = NNMbxmar;
cmdp->cmd.rcmd.marking = marking;
}
return cmdp;
}
./ ADD NAME=NNMBPNNT,SSI=01000022
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: NNTP
*
* Syntax: NNTP {datum}* ;
*
* Mode: any (but see notes)
*
* Function: Sends an NNTP protocol command to the server as built
* from the specified data items. Items can be:
*
* * text strings
* * integers
* * words representing variables that have values
*
* Note: When words are used, the values they represent must be
* valid for the mode in which the EXEC is executed.
*
* Note: The NNTP request must be appropriate for the mode active
* at the time the request is executed.
*
* Note: Since the command can span input lines and the number of
* arguments is variable, the arguments MUST be terminated
* by a semicolon or end of file.
*
* Examples: NNTP "HELP";
* NNTP "ARTICLE " NUMBER;
*
*====================================================================*/
#pragma csect(code, "NN@BPNNT")
#pragma csect(static,"NN$BPNNT")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch NNTP command. ****************************/
static void
NNMbxnnt(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
char *string;
string = NNMbbexp(np,bp,cmdp->cmd.mcmd.ptreep,STRING_SYMTYPE);
if (bp->runtime_error) {
fprintf(np->batch_outfile,
"NNTP command not sent due to errors building argument\n");
return;
}
if (!NNMbconn(np,bp)) { /* Insure server name and connect to server */
fprintf(np->batch_outfile,"NNTP command not executed:\n%s\n\n",
string);
return;
}
fprintf(np->batch_outfile, "NNTP command:\n%s\n\n", string);
if (*string || np->receiving_text) {
if (strlen(string) > CLIENT_BUF_MSGSIZE) {
ERR1(
"Requested NNTP command is longer than NNMVS is prepared to handle."
);
}
else {
strcpy(np->nntp_command,string);
NNMnntp(np); /* execute NNTP commands */
}
}
return;
}
/****** Parse batch NNTP command. ****************************/
struct newscmd *
NNMbpnnt(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
struct ptree *treep = NULL;
treep = NNMbgexp(np,bp,STRING_SYMTYPE); /* Get data string struct */
if (!treep) {
NNMbsynt(np,bp,NULL,0,"Error in arguments to NNTP");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for NNTP command");
if (cmdp) {
cmdp->mode = ANY_MODE;
cmdp->proc = NNMbxnnt;
cmdp->cmd.mcmd.ptreep = treep;
}
return cmdp;
}
./ ADD NAME=NNMBPPUT,SSI=01000024
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: PUT
*
* Syntax: PUT {datum}* ;
*
* Mode: any (but see note)
*
* Function: Writes zero or more items of data to the output file,
* followed by a newline. Items can be:
*
* * text strings
* * integers
* * words representing variables that have values
*
* Note: When words are used, the values they represent must be
* valid for the mode in which the PUT is executed.
*
* Note: Since the command can span input lines and the number of
* arguments is variable, the arguments MUST be terminated
* by a semicolon or end of file.
*
* Examples: PUT;
* PUT "Hello, world";
* PUT 666 " is the number of the Beast.";
* PUT "I have " UNREAD " new items from server " server ".";
*
*====================================================================*/
#pragma csect(code, "NN@BPPUT")
#pragma csect(static,"NN$BPPUT")
#include "nn.h"
#include "nnbatch.h"
/****** Print text line. *********************************************/
static Bool
print_text_line(fp,string)
FILE *fp;
char *string;
{
char *cp;
int l;
for (cp = string, l = strlen(string); l > 0; cp += 251, l -= 251) {
fwrite(cp,(l>251 ? 251 : l),1,fp);
if (ferror(fp)) return FALSE;
if (fputc('\n',fp) == EOF) return FALSE;
}
return TRUE;
}
/****** Execute batch PUT command. ****************************/
static void
NNMbxput(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
struct ptree *treep;
char *string;
FILE *fp;
Bool print_error;
treep = cmdp->cmd.mcmd.ptreep;
print_error = FALSE;
if (!treep) {
fp = NNMbsout(np,bp); /* Set output file */
fprintf(fp,"\n");
if (ferror(fp)) print_error = TRUE;
}
else {
string = NNMbbexp(np,bp,treep,STRING_SYMTYPE);
if (bp->runtime_error) {
fprintf(np->batch_outfile,
"\n<<Put failed, error building argument>>\n");
}
else {
fp = NNMbsout(np,bp); /* Set output file */
if (!print_text_line(fp,string)) print_error = TRUE;
}
}
if (print_error) {
fprintf(stderr,"Error writing to outfile\n");
bp->runtime_error = TRUE;
}
return;
}
/****** Parse batch PUT command. ****************************/
struct newscmd *
NNMbpput(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
struct ptree *treep = NULL;
/*
* Special case for PUT without arguments
*
*/
if (NNMbgtok(np,bp,TOKEN_PEEK)) { /* Peek next token */
switch (bp->nextok.type) {
case EOF_TOKEN:
case EOL_TOKEN:
case SEMI_TOKEN: treep = NULL;
break;
default:
treep = NNMbgexp(np,bp,STRING_SYMTYPE);
if (!treep) {
NNMbsynt(np,bp,NULL,0,
"Error in arguments to PUT");
return NULL;
}
break;
}
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for PUT command");
if (cmdp) {
cmdp->mode = ANY_MODE;
cmdp->proc = NNMbxput;
cmdp->cmd.mcmd.ptreep = treep;
}
return cmdp;
}
./ ADD NAME=NNMBPQUE,SSI=01010013
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: QUERY
*
* Syntax: QUERY
*
* Mode: per_newsgroup or per_article
*
* Function: Dumps the status of the current newsgroup or article.
*
* Examples: QUERY
*
*====================================================================*/
#pragma csect(code, "NN@BPQUE")
#pragma csect(static,"NN$BPQUE")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch QUERY command. ****************************/
static void
NNMbxque(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
switch (cmdp->mode) {
case PER_NEWSGROUP_MODE: NNMqng(np,bp->gp); break;
case PER_ARTICLE_MODE: NNMqar(np,VARK2PARTICLE(*bp->vp)); break;
}
return;
}
/****** Parse batch QUERY command. ****************************/
struct newscmd *
NNMbpque(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp;
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"QUERY"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
switch (bp->mode) {
case PER_NEWSGROUP_MODE:
case PER_ARTICLE_MODE:
break;
default:
NNMbsynt(np,bp,NULL,0,
"QUERY is valid only in per-newsgroup or per-article mode");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for QUERY command");
if (cmdp) {
cmdp->mode = bp->mode;
cmdp->proc = NNMbxque;
}
return cmdp;
}
./ ADD NAME=NNMBPQUI,SSI=01000018
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: QUIT
*
* Syntax: QUIT
*
* Mode: any
*
* Function: Terminates processing when it is seen.
*
* Note: Arguments are not permitted. If they are given, the QUIT
* function will not be performed.
*
* Examples: QUIT
*
*====================================================================*/
#pragma csect(code, "NN@BPQUI")
#pragma csect(static,"NN$BPQUI")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch QUIT command. ****************************/
static void
NNMbxqui(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
bp->quit = TRUE;
fprintf(np->batch_outfile,"\nQUIT signalled. Processing ended.\n");
return;
}
/****** Parse batch QUIT command. ****************************/
struct newscmd *
NNMbpqui(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp;
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"QUIT"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for QUIT command");
if (cmdp) {
cmdp->mode = ANY_MODE;
cmdp->proc = NNMbxqui;
}
return cmdp;
}
./ ADD NAME=NNMBPREG,SSI=01000034
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: REGISTER
*
* Syntax: REGISTER
*
* Mode: per_newsgroup
*
* Function: Registers the current newsgroup.
*
* Note: Arguments are not permitted. If they are given, the
* function will not be performed.
*
* Examples: REGISTER
*
*====================================================================*/
#pragma csect(code, "NN@BPREG")
#pragma csect(static,"NN$BPREG")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch REGISTER command. ******************************/
static void
NNMbxreg(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
Rstruc newsgroup *gp = bp->gp;
gp->registered = 1;
fprintf(np->batch_outfile,"Newsgroup %s registered.\n",gp->name);
NNMsave(np,NULL); /* Checkpoint NEWSRC file */
return;
}
/****** Parse batch REGISTER command. ********************************/
struct newscmd *
NNMbpreg(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp;
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"REGISTER"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
if (bp->mode != PER_NEWSGROUP_MODE) {
NNMbsynt(np,bp,NULL,0,
"REGISTER is invalid outside of per-newsgroup mode");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for REGISTER command");
if (cmdp) {
cmdp->mode = PER_NEWSGROUP_MODE;
cmdp->proc = NNMbxreg;
}
return cmdp;
}
./ ADD NAME=NNMBPSET,SSI=01000038
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: SET
*
* Syntax: SET variablename {=} {value-datum}*
*
* Mode: any (but see note)
*
* Function: Assigns a value to the specified variablename so
* that it can be referenced in later PUT statements or
* condition queries. Value can be made up of:
*
* * text strings
* * integers
* * words representing other variables that have values
*
* Note: When words are used, the values they represent must be
* valid for the mode in which the SET is executed.
*
* Note: Since the command can span input lines and the number of
* arguments is variable, the arguments MUST be terminated
* by a semicolon or end of file.
*
* Note: The type of the value is determined by the declared type
* of the variable being set.
*
* Examples: SET SERVER "foo.news.com"
* SET COUNT = 1
* SET MESSAGE = "There are " UNREAD "new items."
*
*====================================================================*/
#pragma csect(code, "NN@BPSET")
#pragma csect(static,"NN$BPSET")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch SET command. ****************************/
static void
NNMbxset(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
char *string;
int number;
Fool flag;
char *var;
var = cmdp->cmd.scmd.set_symbol;
switch (cmdp->cmd.scmd.set_type) {
case STRING_SYMTYPE:
string = (char *)
NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,STRING_SYMTYPE);
if (!bp->runtime_error) {
SETC(var,string);
}
break;
case NUMBER_SYMTYPE:
number = (int)
NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,NUMBER_SYMTYPE);
if (!bp->runtime_error) {
SETA(var,number);
}
break;
case FLAG_SYMTYPE:
flag = (Fool)
NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,FLAG_SYMTYPE);
if (!bp->runtime_error) {
SETB(var,flag);
}
break;
default:
fprintf(np->batch_outfile,
"Set of %s failed due to unrecognized var type\n", var);
}
if (bp->runtime_error) {
fprintf(np->batch_outfile,
"Set of %s failed due to errors building value\n", var);
}
return;
}
/****** Parse batch SET command. ****************************/
struct newscmd *
NNMbpset(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp = NULL;
struct ptree *treep = NULL;
char *var = NULL;
enum symtype type;
/* Next token must be variable name. */
if (!NNMbgtok(np,bp,TOKEN_READ)) return NULL; /* get token */
if (bp->curtok.type != WORD_TOKEN) {
NNMbsynt(np,bp,NULL,0, "Expected SET variable name not seen");
NNMbflus(np,bp); /* flush input tokens */
return NULL;
}
var = NNMcopy(np,bp->curtok.string);
/* Variable must have been declared, else it is not valid. */
if (!(type = (enum symtype)NNMbvget(np,bp,var,NO_SYMTYPE))) {
NNMbsynt(np,bp,var,0,"Variable has not been declared");
NNMbflus(np,bp); /* flush input tokens */
return NULL;
}
/*
* Next token must be either an equal sign or the first of a series
* of "datums". If the latter, assume the former was present.
*/
if (!NNMbgtok(np,bp,TOKEN_PEEK)) return NULL; /* Peek next token */
if (bp->nextok.type == EQ_TOKEN) {
(void)NNMbgtok(np,bp,TOKEN_FLUSH); /* Eat the '=' */
}
/*
* Rest of tokens define the string to which the variable must be set.
* Note that the type (returned by NNMbvget) is the type of the
* variable in question, defining the type of its value.
*/
treep = NNMbgexp(np,bp,type); /* Get structure describing data */
if (!treep) {
NNMbsynt(np,bp,NULL,0,"Bad arguments to SET, need '=' or data");
return NULL;
}
GETMAIN(cmdp, struct newscmd, 1, "newscmd for SET command");
if (cmdp) {
cmdp->mode = ANY_MODE;
cmdp->proc = NNMbxset;
cmdp->cmd.scmd.ptreep = treep;
cmdp->cmd.scmd.set_symbol = var;
cmdp->cmd.scmd.set_type = type;
}
return cmdp;
}
./ ADD NAME=NNMBPVAR,SSI=01000001
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/*=====================================================================
*
* Command: VARS
*
* Syntax: VARS
*
* Mode: any
*
* Function: Displays all defined variables and their types and values.
*
* Examples: VARS
*
*====================================================================*/
#pragma csect(code, "NN@BPVAR")
#pragma csect(static,"NN$BPVAR")
#include "nn.h"
#include "nnbatch.h"
/****** Dump variable name, type and value. **************************/
static void
dump_variable(np,bp,symp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc symtab *symp;
{
if (!symp) return;
fprintf(np->batch_outfile, " %-16.16s ", symp->symvar);
switch (symp->type) {
case STRING_SYMTYPE:
fprintf(np->batch_outfile, "STRING %s\n", symp->symval);
break;
case NUMBER_SYMTYPE:
fprintf(np->batch_outfile, "NUMBER %d\n", symp->symnum);
break;
case FLAG_SYMTYPE:
fprintf(np->batch_outfile, "FLAG %s\n",
symp->symnum ? "TRUE" : "FALSE");
break;
}
return;
}
/****** Display variable. ********************************************/
static void
display_variable(np,bp,symp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc symtab *symp;
{
if (!symp) return;
if (symp->left) display_variable(np,bp,symp->left);
dump_variable(np,bp,symp);
if (symp->right) display_variable(np,bp,symp->right);
return;
}
/****** Execute batch VARS command. ****************************/
static void
NNMbxvar(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
fprintf(np->batch_outfile, "Current variables follow\n\n");
display_variable(np,bp,bp->symtabp);
fprintf(np->batch_outfile, "\nEnd variable display\n");
return;
}
/****** Parse batch VARS command. ****************************/
struct newscmd *
NNMbpvar(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
struct newscmd *cmdp;
bp->stop_at_newline = TRUE;
NNMbtras(np,bp,"VARS"); /* Trash extraneous parameters */
if (bp->syntax_error) return NULL;
GETMAIN(cmdp, struct newscmd, 1, "newscmd for VARS command");
if (cmdp) {
cmdp->mode = ANY_MODE;
cmdp->proc = NNMbxvar;
}
return cmdp;
}
./ ADD NAME=NNMBSOUT,SSI=01020001
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BSOUT")
#pragma csect(static,"NN$BSOUT")
#include "nn.h"
#include "nnbatch.h"
/****** Set the output file from the OUTFILE variable. ***************/
FILE *
NNMbsout(np,bp)
Rstruc nncb *np;
Rstruc batch *bp;
{
char *outfile;
FILE *outfp = NULL;
FILE *infp = NULL;
Bool appending;
outfile = GETC("OUTFILE");
if (!outfile) outfile = "";
if (bp->outfilename && EQUAL(bp->outfilename,outfile)) {
if (!bp->outfp) outfp = np->batch_outfile;
else outfp = bp->outfp;
}
else {
if (bp->outfp) {
if (fclose(bp->outfp) < 0) {
fprintf(stderr,"Error closing outfile\n");
bp->runtime_error = TRUE;
}
fprintf(np->batch_outfile,"Ending output to %s\n",bp->outfilename);
bp->outfp = NULL;
bp->outfilename = NULL;
}
if (*outfile) {
if (TEST_IF_FILE_EXISTS(infp,outfile)) {
CLEANUP_IF_FILE_EXISTS(infp);
appending = TRUE;
}
else {
appending = FALSE;
}
outfp = OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(outfile,appending);
if (!outfp) {
perror(outfile);
fprintf(np->batch_outfile,"Error: OUTFILE %s is not usable.\n",
outfile);
bp->runtime_error = TRUE;
}
else {
bp->outfp = outfp;
bp->outfilename = NNMcopy(np,outfile);
fprintf(np->batch_outfile,"Beginning output to %s\n", outfile);
}
}
else {
outfp = np->batch_outfile;
bp->outfp = NULL;
bp->outfilename = NULL;
}
}
return outfp;
}
./ ADD NAME=NNMBSYNT,SSI=01000013
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BSYNT")
#pragma csect(static,"NN$BSYNT")
#include "nn.h"
#include "nnbatch.h"
/****** Syntax error. ************************************************/
void
NNMbsynt(np,bp,cp,len,msg)
Rstruc nncb *np;
Rstruc batch *bp;
char *cp;
int len;
char *msg;
{
if (cp && len == 0) len = strlen(cp);
if (!cp) {
fprintf(np->batch_outfile, "Syntax error: %s.\n", msg);
}
else {
fprintf(np->batch_outfile, "Syntax error: %s. Token: %*.*s\n",
msg, len, len, cp);
}
bp->syntax_error = TRUE;
bp->curtok.type = ERROR_TOKEN;
bp->nextok.type = NO_TOKEN;
bp->input_errors++;
return;
}
./ ADD NAME=NNMBTEXT,SSI=01000037
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BTEXT")
#pragma csect(static,"NN$BTEXT")
#include "nn.h"
#include "nnbatch.h"
/****** Print text lines. ********************************************/
static int
print_text_lines(np,bp,fp,textp,linep,extracting)
Rstruc nncb *np;
Rstruc batch *bp;
FILE *fp;
struct textline *textp;
char **linep;
Fool extracting;
{
struct textline *tp;
char *cp;
int l;
int write_error;
Bool tab_expanding;
Bool appending;
Bool blank_before_separator;
char *separator_line;
if (!fp) return TRUE;
if (extracting) {
tab_expanding = np->extract_tab_expanding;
appending = np->extract_appending;
blank_before_separator = np->extract_blank_before_separator;
separator_line = np->extract_separator_line;
}
else {
tab_expanding = TRUE;
appending = FALSE;
blank_before_separator = FALSE;
separator_line = "";
}
tab_expanding = extracting ? np->extract_tab_expanding
: GETB("TABEXPAND");
write_error = 0;
/* If append mode, and a separator line was specified, use it. */
while (appending && separator_line && *separator_line) {
if (fprintf(fp,"%s\n",separator_line) < 0) {
*linep = separator_line;
write_error = 1;
break;
}
if (blank_before_separator) {
if (fprintf(fp,"\n") < 0) {
*linep = "<blank before separator>";
write_error = 2;
break;
}
}
break;
}
for (tp=textp; tp && !write_error; tp=tp->next) {
if (tp->text_length == 0) {
if (fputc('\n',fp) == EOF) {
*linep = "<single newline character>";
write_error = 3;
break;
}
}
else if (tp->text_length > 0) {
if (tab_expanding) {
cp = tp->tab_expanded_text;
l = tp->tab_expanded_text_length;
}
else {
cp = tp->text;
l = tp->text_length;
}
for (; l > 0; cp += 251, l -= 251) {
fwrite(cp,(l>251 ? 251 : l),1,fp);
if (ferror(fp)) {
*linep = cp;
write_error = 4;
break;
}
if (fputc('\n',fp) == EOF) {
*linep = "<single newline character>";
write_error = 5;
break;
}
}
}
}
if (write_error) return write_error;
if (ferror(fp)) {
*linep = "<ferror occurred>";
return -1;
}
else return 0;
}
/****** Process the lines of text retrieved from server. *************/
void
NNMbtext(np,thp,fp)
Rstruc nncb *np;
struct texthdr *thp;
FILE *fp;
{
Rstruc batch *bp = np->batch_hook;
int rc;
char *line;
Fool extracting;
if (fp) { /* file pointer passed :: called from EXTRACT command */
extracting = TRUE;
}
else {
fp = NNMbsout(np,bp); /* set output file */
extracting = FALSE;
}
rc = print_text_lines(np,bp,fp,thp->first_text_line,&line,extracting);
if (rc != 0) {
fprintf(stderr,"Error %d writing text to outfile\n",rc);
fprintf(stderr,"Line: %s\n",line);
bp->runtime_error = TRUE;
}
return;
}
./ ADD NAME=NNMBTRAS,SSI=01000033
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BTRAS")
#pragma csect(static,"NN$BTRAS")
#include "nn.h"
#include "nnbatch.h"
/****** Trash extraneous data in command line. ***********************/
void
NNMbtras(np,bp,name)
Rstruc nncb *np;
Rstruc batch *bp;
char *name;
{
struct token *tp;
Bool finished = FALSE;
char tmp[81];
/*
* Pull tokens until semicolon or EOF. Note that EOL will not be
* considered the end of the datum stream, because the user may wish
* to specify a long list that takes several lines. Therefore, an
* explicit semicolon is required to terminate the list.
*/
while (!finished && (tp = PEEK())) {
switch (tp->type) {
case EOL_TOKEN:
case EOF_TOKEN:
case SEMI_TOKEN: EAT();
finished = TRUE;
break;
default: EAT();
sprintf(tmp,"Extraneous data in %s command",name);
NNMbsynt(np,bp,tp->string,0,tmp);
break;
}
}
return;
}
./ ADD NAME=NNMBVGET,SSI=01000041
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BVGET")
#pragma csect(static,"NN$BVGET")
#include "nn.h"
#include "nnbatch.h"
/****** Report type mismatch error. **********************************/
static void
type_error(np,var,type1,type2)
Rstruc nncb *np;
char *var;
char *type1;
char *type2;
{
ERR4("Type mismatch: \
Cannot retrieve a value of type %s from %s variable %s.",
type1,type2,var);
return;
}
/****** Get a value from the symbol table. ***************************/
ANYTYPE
NNMbvget(np,bp,var,type)
Rstruc nncb *np;
Rstruc batch *bp;
char *var;
enum symtype type;
{
Rstruc symtab *symp;
int varlen;
char vartest[MAX_SYMBOL_LENGTH];
varlen = strlen(var);
if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
ERR2(
"A variable name must be between 1 and %d characters in length.",
MAX_SYMBOL_LENGTH);
return FALSE;
}
memset(vartest,'\0',MAX_SYMBOL_LENGTH);
memcpy(vartest,var,varlen);
symp = bp->symtabp;
while (symp) {
switch (memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH)) {
case 0: /* equal */
break;
case 1: /* greater */
symp = symp->right;
continue;
default: /* less */
symp = symp->left;
continue;
}
break;
}
/* Special case, just to see if the variable exists or not. */
if (type == NO_SYMTYPE)
return (symp ? (ANYTYPE)symp->type : (ANYTYPE)NO_SYMTYPE);
if (!symp) {
ERR2("The variable %s has not been declared or set to a value.",var);
return NULL;
}
/*------------------------------------------------------------------*
* *
* Table of allowable type-to-type settings: *
* *
* symp->type | type | result *
*____________|_____________|_________________________________ *
* STRING | STRING | OK *
* | NUMBER | error *
* | FLAG | error *
*____________|_____________|_________________________________ *
* NUMBER | STRING | convert to string via sprintf %d *
* | NUMBER | OK *
* | FLAG | interpret as nonzero or zero *
*____________|_____________|_________________________________ *
* FLAG | STRING | convert to "1" or "0" *
* | NUMBER | convert to 1 or 0 *
* | FLAG | OK *
* | | *
*------------------------------------------------------------------*/
switch (symp->type) {
case STRING_SYMTYPE:
switch (type) {
case STRING_SYMTYPE: return (ANYTYPE)symp->symval;
case NUMBER_SYMTYPE: type_error(np,var,"NUMBER","STRING");
break;
case FLAG_SYMTYPE: type_error(np,var,"FLAG","STRING");
break;
}
break;
case NUMBER_SYMTYPE:
switch (type) {
case STRING_SYMTYPE: sprintf(symp->symval,"%d",symp->symnum);
return (ANYTYPE)symp->symval;
case NUMBER_SYMTYPE: return (ANYTYPE)symp->symnum;
case FLAG_SYMTYPE: return (symp->symnum
? (ANYTYPE)1 : (ANYTYPE)0);
}
break;
case FLAG_SYMTYPE:
switch (type) {
case STRING_SYMTYPE: return (symp->symnum
? (ANYTYPE)"1" : (ANYTYPE)"0");
case NUMBER_SYMTYPE: return (symp->symnum
? (ANYTYPE)1 : (ANYTYPE)0);
case FLAG_SYMTYPE: return (symp->symnum
? (ANYTYPE)1 : (ANYTYPE)0);
}
break;
}
return NULL;
}
./ ADD NAME=NNMBVPUT,SSI=01000021
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BVPUT")
#pragma csect(static,"NN$BVPUT")
#include "nn.h"
#include "nnbatch.h"
/****** Report type mismatch error. **********************************/
static void
type_error(np,var,type1,type2)
Rstruc nncb *np;
char *var;
char *type1;
char *type2;
{
ERR4("Type mismatch: \
Cannot assign a value of type %s to %s variable %s.",
type1,type2,var);
return;
}
/****** Set value of symbol table entry. *****************************/
static void
set_value(np,sp,var,val,type)
Rstruc nncb *np;
struct symtab *sp;
char *var;
ANYTYPE val;
enum symtype type;
{
/*------------------------------------------------------------------*
* *
* Table of allowable type-to-type settings: *
* *
* sp->type | type | result *
*____________|_____________|_________________________________ *
* STRING | STRING | OK *
* | NUMBER | convert to string via sprintf %d *
* | FLAG | error *
*____________|_____________|_________________________________ *
* NUMBER | STRING | error *
* | NUMBER | OK *
* | FLAG | convert to 1 or 0 *
*____________|_____________|_________________________________ *
* FLAG | STRING | error *
* | NUMBER | interpret as nonzero or zero *
* | FLAG | OK *
* | | *
*------------------------------------------------------------------*/
switch (sp->type) {
case STRING_SYMTYPE:
switch (type) {
case STRING_SYMTYPE: strcpy(sp->symval,(char *)val);
break;
case NUMBER_SYMTYPE: sprintf(sp->symval,"%d",(int)val);
break;
case FLAG_SYMTYPE: type_error(np,var,"FLAG","STRING");
break;
}
break;
case NUMBER_SYMTYPE:
switch (type) {
case STRING_SYMTYPE: type_error(np,var,"STRING","NUMBER");
break;
case NUMBER_SYMTYPE: sp->symnum = (int)val;
break;
case FLAG_SYMTYPE: sp->symnum = (Fool)val ? 1 : 0;
break;
}
break;
case FLAG_SYMTYPE:
switch (type) {
case STRING_SYMTYPE: type_error(np,var,"STRING","FLAG");
break;
case NUMBER_SYMTYPE: sp->symnum = (int)val ? 1 : 0;
break;
case FLAG_SYMTYPE: sp->symnum = (Fool)val ? 1 : 0;
break;
}
break;
}
if (np->debug_file) {
switch (sp->type) {
case STRING_SYMTYPE: fprintf(np->debug_file,
"NNMbvput: %s set to '%s'\n",
sp->symvar, sp->symval);
break;
case NUMBER_SYMTYPE: fprintf(np->debug_file,
"NNMbvput: %s set to %d\n",
sp->symvar, sp->symnum);
break;
case FLAG_SYMTYPE: fprintf(np->debug_file,
"NNMbvput: %s set to %s\n",
sp->symvar,
sp->symnum ? "TRUE" : "FALSE");
break;
}
}
return;
}
/****** Put a value into the symbol table. ***************************/
void
NNMbvput(np,bp,var,type,val)
Rstruc nncb *np;
Rstruc batch *bp;
char *var;
enum symtype type;
ANYTYPE val;
{
Rstruc symtab *symp;
Rstruc symtab **sympref;
struct symtab *sympnew;
struct symtab *sympleft;
struct symtab *sympright;
enum symtype symptype;
int varlen;
int minimum_value_length;
int getlen;
int comp;
Bool symbol_found;
char vartest[MAX_SYMBOL_LENGTH];
varlen = strlen(var);
if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
ERR2(
"A variable name must be between 1 and %d characters in length.",
MAX_SYMBOL_LENGTH);
return;
}
memset(vartest,'\0',MAX_SYMBOL_LENGTH);
memcpy(vartest,var,varlen);
switch (type) {
case STRING_SYMTYPE: minimum_value_length = strlen((char *)val) + 1;
break;
case NUMBER_SYMTYPE: minimum_value_length = 12;
break;
case FLAG_SYMTYPE: minimum_value_length = 6;
break;
}
symbol_found = FALSE;
sympleft = NULL;
sympright = NULL;
sympref = &bp->symtabp;
while ((symp=*sympref)) {
switch ((comp=memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH))) {
case 0: /* equal */
symbol_found = TRUE;
/* free this entry and allocate a new one if this one
is too small to hold the requested value */
if (minimum_value_length > symp->vallen) {
symptype = symp->type;
sympleft = symp->left;
sympright = symp->right;
FREEMAIN(*sympref,"old symbol table entry");
*sympref = NULL;
break;
}
else {
set_value(np,symp,var,val,type);
return;
}
case 1: /* greater */
sympref = &symp->right;
continue;
default: /* less */
sympref = &symp->left;
continue;
}
}
/* Symbol not found - not allowed, means variable not declared */
if (!symbol_found) {
ERR2("The variable %s has not been declared or set to a value.",var);
return;
}
getlen = offsetof(struct symtab, symval) + minimum_value_length;
GETMAIN(sympnew, char, getlen, "new symbol table entry");
if (!sympnew) {
ERR2("Cannot set variable: \
Unable to allocate storage to hold value for variable %s.",
var);
return;
}
memcpy(sympnew->symvar, vartest, MAX_SYMBOL_LENGTH);
sympnew->left = sympleft;
sympnew->right = sympright;
sympnew->vallen = minimum_value_length;
sympnew->type = symptype;
*sympref = sympnew;
set_value(np,sympnew,var,val,type);
return;
}
./ ADD NAME=NNMBXFAR,SSI=01040032
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BXFAR")
#pragma csect(static,"NN$BXFAR")
#include "nn.h"
#include "nnbatch.h"
/****** Execute batch FOR articles command. **************************/
struct variablesave {
int number;
Bool read;
Bool missing;
char *subject;
char *date;
char *from;
char *messageid;
};
/****** Set article variables. ***************************************/
static void
set_article_variables(np,bp,vp,anum,vsp)
Rstruc nncb *np;
Rstruc batch *bp;
VARK *vp;
int anum;
struct variablesave *vsp;
{
Rstruc newsarticle *ap = VARK2PARTICLE(*vp);
vsp->number = GETA("NUMBER");
vsp->read = GETB("READ");
vsp->missing = GETB("MISSING");
vsp->subject = NNMcopy(np,GETC("SUBJECT"));
vsp->date = NNMcopy(np,GETC("DATE"));
vsp->from = NNMcopy(np,GETC("FROM"));
vsp->messageid = NNMcopy(np,GETC("MESSAGEID"));
SETA("NUMBER", anum);
SETB("READ", IsRead(*vp));
if (IsMissing(*vp)) {
SETB("MISSING", TRUE);
SETC("SUBJECT", "");
SETC("DATE", "");
SETC("FROM", "");
SETC("MESSAGEID", "");
}
else {
SETB("MISSING", FALSE);
SETC("SUBJECT", ap->subject);
SETC("DATE", ap->date);
SETC("FROM", ap->from);
SETC("MESSAGEID", ap->message_id);
}
return ;
}
/****** Unset article variables. *************************************/
static void
unset_article_variables(np,bp,vsp)
Rstruc nncb *np;
Rstruc batch *bp;
struct variablesave *vsp;
{
SETA("NUMBER", vsp->number);
SETB("READ", vsp->read);
SETB("MISSING", vsp->missing);
SETC("SUBJECT", vsp->subject);
SETC("DATE", vsp->date);
SETC("FROM", vsp->from);
SETC("MESSAGEID", vsp->messageid);
FREEMAIN(vsp->subject, "saved copy of SUBJECT");
FREEMAIN(vsp->date, "saved copy of DATE");
FREEMAIN(vsp->from, "saved copy of FROM");
FREEMAIN(vsp->messageid, "saved copy of MESSAGEID");
return;
}
/****** Reset newsgroup variables. ***********************************/
static void
reset_newsgroup_variables(np,bp,gp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
{
SETA("COUNT" ,gp->article_count);
SETA("UNREAD" ,gp->unread_count);
SETA("FIRST" ,gp->low_number);
SETA("LAST" ,gp->high_number);
return ;
}
/****** Execute article commands. ************************************/
static void
execute_article_commands(np,bp,vp,treep)
Rstruc nncb *np;
Rstruc batch *bp;
VARK *vp;
struct cmdtree *treep;
{
VARK *savevp;
for (; treep; treep = treep->next) {
bp->runtime_error = FALSE;
savevp = bp->vp;
bp->vp = vp;
(treep->cmd->proc) (np,bp,treep->cmd);
bp->vp = savevp;
SETB("ERROR",bp->runtime_error);
}
return;
}
/****** Test if article passes filter. *****************************/
static Bool
pass_filter(np,bp,filter)
Rstruc nncb *np;
Rstruc batch *bp;
struct ptree *filter;
{
Bool passes_filter;
if (filter) {
passes_filter = (Fool)NNMbbexp(np,bp,filter,FLAG_SYMTYPE);
if (bp->runtime_error) {
bp->request_errors++;
passes_filter = FALSE;
}
}
else passes_filter = TRUE;
return passes_filter;
}
/****** Test if article passes criterion. ****************************/
static Bool
pass_criterion(np,bp,vp,anum,which,first,last)
Rstruc nncb *np;
Rstruc batch *bp;
VARK *vp;
int anum;
enum which_articles which;
struct ptree *first;
struct ptree *last;
{
int firstnum;
int lastnum;
switch (which) {
case ALL_ARTICLES:
return TRUE;
case READ_ARTICLES:
return (IsRead(*vp));
case UNREAD_ARTICLES:
return (IsUnread(*vp));
case RANGED_ARTICLES:
if (first)
firstnum = (int)NNMbbexp(np,bp,first,NUMBER_SYMTYPE);
else firstnum = FIRST_ARTICLE_IN_RANGE;
if (last)
lastnum = (int)NNMbbexp(np,bp,last, NUMBER_SYMTYPE);
else lastnum = firstnum;
return (anum >= firstnum && anum <= lastnum);
case NO_ARTICLES:
return FALSE;
default:
return FALSE;
}
}
/****** Execute batch FOR articles command. **************************/
void
NNMbxfar(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
Rstruc newsgroup *gp;
Rstruc newsarticle *ap;
VARK *vp;
struct ptree *filter;
struct cmdtree *treep;
struct ptree *first;
struct ptree *last;
int anum;
enum which_articles which;
struct variablesave varsave;
filter = cmdp->cmd.ncmd.fors.filter;
treep = cmdp->cmd.ncmd.fors.treep;
which = cmdp->cmd.ncmd.fors.crit.which;
first = cmdp->cmd.ncmd.fors.crit.first;
last = cmdp->cmd.ncmd.fors.crit.last;
gp = bp->gp;
/* Logic: (1) apply "which" criteria
* (2) set variables for articles remaining
* (3) apply filters
* Rationale: Variables must be set before filters can use them.
* But criteria can be used to reduce the load.
*/
np->current_newsgroup = gp;
np->newsgroup_selected = FALSE;
if (!GroupSelected(gp)) gp = NNMdng(np,gp,NULL);
if (!gp) return;
bp->gp = gp;
reset_newsgroup_variables(np,bp,gp);
if (gp->article_vector) {
for (anum = gp->vector_first; anum <= gp->vector_last; anum++) {
vp = &GETVARK(gp,anum);
if (pass_criterion(np,bp,vp,anum,which,first,last)) {
if (NNMrarh(np,gp,vp,anum,NULL)) { /* retrieve article hdr */
set_article_variables(np,bp,vp,anum,&varsave);
if (pass_filter(np,bp,filter)) {
execute_article_commands(np,bp,vp,treep);
}
unset_article_variables(np,bp,&varsave);
}
}
}
}
np->current_newsgroup = NULL;
np->newsgroup_selected = FALSE;
return;
}
./ ADD NAME=NNMBXFNG,SSI=01040010
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@BXFNG")
#pragma csect(static,"NN$BXFNG")
#include "nn.h"
#include "nnbatch.h"
struct variablesave {
char *group;
Bool registered;
Bool newgroup;
Bool nosuchgroup;
int count;
int unread;
int first;
int last;
};
/****** Set newsgroup variables. *************************************/
static void
set_newsgroup_variables(np,bp,gp,vsp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
struct variablesave *vsp;
{
vsp->group = NNMcopy(np,GETC("GROUP"));
vsp->registered = GETB("REGISTERED");
vsp->newgroup = GETB("NEWGROUP");
vsp->nosuchgroup = GETB("NOSUCHGROUP");
vsp->count = GETA("COUNT");
vsp->unread = GETA("UNREAD");
vsp->first = GETA("FIRST");
vsp->last = GETA("LAST");
SETC("GROUP" ,gp->name);
SETA("COUNT" ,gp->article_count);
SETA("UNREAD" ,gp->unread_count);
SETA("FIRST" ,gp->low_number);
SETA("LAST" ,gp->high_number);
SETB("REGISTERED" ,(gp->registered > 0) ? TRUE : FALSE);
if (NewGroup(gp)) { /* if new newsgroup */
fprintf(np->batch_outfile,"New newsgroup: %s (%d articles)\n",
gp->name, gp->article_count);
gp->registered = -1;
SETB("NEWGROUP",TRUE);
}
else if (gp->registered == -1) { /* old way: if new newsgroup */
fprintf(np->batch_outfile,"New newsgroup: %s (%d articles)\n",
gp->name, gp->article_count);
SetNewGroup(gp);
SETB("NEWGROUP",TRUE);
}
else {
OffNewGroup(gp);
SETB("NEWGROUP",FALSE);
}
if (BogusGroup(gp)) {
fprintf(np->batch_outfile,"Nonexistent newsgroup: %s\n", gp->name);
SetNoSuchGroup(gp);
SETB("NOSUCHGROUP",TRUE);
}
else {
SETB("NOSUCHGROUP",FALSE);
}
return ;
}
/****** Unset newsgroup variables. **********************************/
static void
unset_newsgroup_variables(np,bp,gp,vsp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
struct variablesave *vsp;
{
SETC("GROUP" ,vsp->group);
SETB("REGISTERED" ,vsp->registered);
SETB("NEWGROUP" ,vsp->newgroup);
SETB("NOSUCHGROUP" ,vsp->nosuchgroup);
SETA("COUNT" ,vsp->count);
SETA("UNREAD" ,vsp->unread);
SETA("FIRST" ,vsp->first);
SETA("LAST" ,vsp->last);
FREEMAIN(vsp->group,"saved copy of GROUP");
return ;
}
/****** See if new newsgroup. ****************************************/
static void
see_if_new_newsgroup(np,bp,gp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
{
if (NewGroup(gp)) { /* if new newsgroup */
if (GETB("AUTOREGISTER")) {
gp->registered = 1;
SETB("REGISTERED",TRUE);
fprintf(np->batch_outfile,
"Added newsgroup %s as REGISTERED\n", gp->name);
}
else {
gp->registered = 0;
SETB("REGISTERED",FALSE);
fprintf(np->batch_outfile,
"Added newsgroup %s as UNREGISTERED\n", gp->name);
}
}
return;
}
/****** See if bogus newsgroup. **************************************/
static void
see_if_bogus_newsgroup(np,bp,gp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
{
if (BogusGroup(gp)) {
if (GETB("AUTODELETE")) {
SetNoSuchGroup(gp);
OffGroupListed(gp);
fprintf(np->batch_outfile, "Deleted newsgroup %s\n", gp->name);
}
else {
SetGroupListed(gp);
fprintf(np->batch_outfile, "Kept newsgroup %s\n", gp->name);
}
}
return;
}
/****** Execute newsgroup commands. **********************************/
static void
execute_newsgroup_commands(np,bp,gp,treep)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
struct cmdtree *treep;
{
struct newsgroup *savegp;
for (; treep; treep = treep->next) {
bp->runtime_error = FALSE;
savegp = bp->gp;
bp->gp = gp;
(treep->cmd->proc) (np,bp,treep->cmd);
bp->gp = savegp;
SETB("ERROR",bp->runtime_error);
}
return;
}
/****** Test if newsgroup passes filter. *****************************/
static Bool
pass_filter(np,bp,gp,filter)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
struct ptree *filter;
{
Bool passes_filter;
if (filter) {
passes_filter = (Fool)NNMbbexp(np,bp,filter,FLAG_SYMTYPE);
if (bp->runtime_error) {
bp->request_errors++;
passes_filter = FALSE;
}
}
else passes_filter = TRUE;
return passes_filter;
}
/****** Match group name against group string. ***********************/
static Bool
match(name,string)
char *name;
char *string;
{
return FALSE;
}
/****** See if group name is in group string. ************************/
static Bool
in(name,string)
char *name;
char *string;
{
char *s;
char *cp1;
char *cp2;
char *cp3;
s = string;
for (;;) {
cp1 = strstr(s,name);
if (!cp1) return FALSE;
cp2 = cp1-1;
if (cp2 < string || *cp2 == ' ' || *cp2 == '\t' || *cp2 == ',') {
cp3 = cp1+strlen(name);
if (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t' || *cp3 == ',') {
return TRUE;
}
}
s = cp1 + 1;
continue;
}
}
/****** Test if newsgroup passes criterion. **************************/
static Bool
pass_criterion(np,bp,gp,which,groups)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newsgroup *gp;
enum which_newsgroups which;
struct ptree *groups;
{
char *groupstring;
if (groups) {
groupstring = NNMbbexp(np,bp,groups,STRING_SYMTYPE);
lowercase_in_place(groupstring);
}
switch (which) {
case ALL_NEWSGROUPS: return TRUE;
case REGISTERED_NEWSGROUPS: return (gp->registered > 0);
case UNREGISTERED_NEWSGROUPS: return (gp->registered == 0);
case NAMED_NEWSGROUPS: return in(gp->name,groupstring);
case MASKED_NEWSGROUPS:
fprintf(np->batch_outfile,"Sorry, cannot handle MASKED_NEWSGROUPS.\n");
return match(gp->name,groupstring);
case NO_NEWSGROUPS: return FALSE;
default: return FALSE;
}
}
/****** Execute batch FOR newsgroups command. ************************/
void
NNMbxfng(np,bp,cmdp)
Rstruc nncb *np;
Rstruc batch *bp;
Rstruc newscmd *cmdp;
{
Rstruc newsgroup *gp;
struct ptree *filter;
struct cmdtree *treep;
struct ptree *groups;
enum which_newsgroups which;
struct variablesave varsave;
Bool serverlist;
filter = cmdp->cmd.icmd.fors.filter;
treep = cmdp->cmd.icmd.fors.treep;
which = cmdp->cmd.icmd.fors.crit.which;
groups = cmdp->cmd.icmd.fors.crit.groups;
/* Connect to server. */
if (!NNMbconn(np,bp)) {
fprintf(np->batch_outfile,"No newsgroup commands executed.\n");
bp->request_errors++;
return;
}
/* Determine source of newsgroups - SERVER or NEWSRC. */
/* If SERVERLIST is true, do an NNTP list. Otherwise */
/* use NEWSRC and do individual group requests... */
/* If we do get the newsgroups via LIST, do it only once. */
serverlist = GETB("SERVERLIST");
if (serverlist) {
if (!bp->newsgroups_retrieved) {
if (!NNMdlang(np,LIST_ALL)) { /* get list of all grps fr server */
fprintf(np->batch_outfile,"No newsgroups processed.\n");
bp->request_errors++;
return;
}
bp->newsgroups_retrieved = TRUE;
}
}
/* Logic: (1) apply "which" criteria
* (2) set variables for groups remaining
* (3) apply filters
* Rationale: Variables must be set before filters can use them.
* But criteria can be used to reduce the load.
*/
/* The list of newsgroups has already been built from newsrc at this
* point. Now, if the source is the server, then ask NNTP to get
* the current list of newsgroups and process it against the list
* from NEWSRC. If the source is NEWSRC, then get the current status
* of each newsgroup via the NNTP "group" command (slow).
*/
/* Note that the position of see_if_new_newsgroup determines if new
* newsgroups are to be registered depending on AUTOREGISTER *after*
* the filtering or *before*. If *after*, then all groups that are
* not handled get autoregistered as DEREGISTERED.
*/
for (gp = np->first_newsgroup; gp; gp = gp->next) {
if (pass_criterion(np,bp,gp,which,groups)) {
if (!serverlist) {
NNMdng(np,gp,NULL); /* do newsgroup by address */
if (np->newsgroup_not_found) {
SetNoSuchGroup(gp);
gp->article_count = 0;
gp->unread_count = 0;
}
}
set_newsgroup_variables(np,bp,gp,&varsave);
if (pass_filter(np,bp,gp,filter)) {
see_if_new_newsgroup(np,bp,gp);
see_if_bogus_newsgroup(np,bp,gp);
if (!NoSuchGroup(gp)) {
execute_newsgroup_commands(np,bp,gp,treep);
}
}
unset_newsgroup_variables(np,bp,gp,&varsave);
}
}
return;
}
./ ADD NAME=NNMCAR,SSI=010C0008
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@CAR ")
#pragma csect(static,"NN$CAR ")
#include "nn.h"
/****** Choose article (Determine if it is eligible for display) *****/
Bool
NNMcar(np,gp,anum,vp,app,cdp,carfun)
Rstruc nncb *np;
Rstruc newsgroup *gp;
int anum;
VARK *vp;
struct newsarticle **app;
struct countdown *cdp;
enum choose_reason carfun;
{
Rstruc newsarticle *ap = NULL;
Bool rc = FALSE;
/* If vp is null, anum must be nonzero.
* If vp is provided, anum may be zero, in which case NNMrarh will
* figure out what it is if it needs to. Not to worry here.
*/
if (!vp) vp = &GETVARK(gp,anum);
if (IsUnknown(*vp)) {
if (np->show_all_articles /* if "A"ll requested */
|| IsUnread(*vp) /* or "S" and article not read */
|| (!np->unread_articles_only /* or article already in table */
&& IsPresent(*vp)
&& (ap=VARK2PARTICLE(*vp)) && ArticleRetrieved(ap))) {
if (*np->article_only_string) {
SetKnownIneligible(*vp);
if (!ap) ap = NNMrarh(np,gp,vp,anum,cdp);
if (ap && IsPresent(*vp)) {
if (NNMstrlc(ap->subject,np->article_only_string)) {
SetKnownEligible(*vp);
rc = TRUE;
}
}
}
else { /* no ONLY string */
if (carfun != MARK_ONLY) {
SetKnownIneligible(*vp);
if (!ap) ap = NNMrarh(np,gp,vp,anum,cdp);
if (ap && IsPresent(*vp)) {
SetKnownEligible(*vp);
rc = TRUE;
}
}
else {
ap = VARK2PARTICLE(*vp);
if (ap != V_NULL_ARTICLE && ap != V_MISSING_ARTICLE) {
rc = TRUE; /* just return for marking, don't set up etc. */
}
}
}
}
else SetKnownIneligible(*vp);
}
if (IsEligible(*vp)) {
rc = TRUE;
if (!ap) ap = VARK2PARTICLE(*vp);
}
if (rc && app) *app = ap;
return rc;
}
./ ADD NAME=NNMCLRNG,SSI=01020039
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@CLRNG")
#pragma csect(static,"NN$CLRNG")
#include "nn.h"
/****** Clear newsgroups. ********************************************/
void
NNMclrng(np)
Rstruc nncb *np;
{
Rstruc newsgroup *gp1;
Rstruc newsgroup *gp2;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
np->newsgroup_selected = FALSE;
np->new_newsgroup_count = 0;
gp1 = np->first_newsgroup;
while (gp1) {
gp2 = gp1->next;
if (gp1->article_vector) {
vpfirst = &GETVARKFIRST(gp1);
vplast = &GETVARKLAST(gp1);
for (vp = vpfirst; vp <= vplast; vp++) {
if (IsPresent(*vp)) {
NNMclrtx(np,VARK2PARTICLE(*vp));
}
}
}
FREEMAIN(gp1->sort_vector, "newsgroup sort vector");
FREEMAIN(gp1->article_vector, "newsgroup article vector");
if (gp1->saved_newsrc_line != gp1->saved_newsrc_data) {
FREEMAIN(gp1->saved_newsrc_line,"newsgroup newsrc line");
}
FREEMAIN(gp1, "newsgroup");
gp1 = gp2;
}
np->first_newsgroup = NULL;
np->first_newsgroup_alt = NULL;
np->current_newsgroup = NULL;
np->last_newsgroup = NULL;
np->last_added_newsgroup = NULL;
return;
}
./ ADD NAME=NNMCLRTX,SSI=01000048
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@CLRTX")
#pragma csect(static,"NN$CLRTX")
#include "nn.h"
/****** Clear text. **************************************************/
void
NNMclrtx(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
Rstruc texthdr *thp;
Rstruc textline *tp1;
Rstruc textline *tp2;
/* If article is not specified, use main nncb, else article's text */
thp = (ap ? &ap->thdr : &np->thdr);
tp1 = thp->first_text_line;
while (tp1) {
tp2 = tp1->next;
FREEMAIN(tp1,"text line");
tp1 = tp2;
}
thp->text_body_line = NULL;
thp->first_text_line = NULL;
thp->current_text_line = NULL;
thp->last_text_line = NULL;
thp->text_line_count = 0;
thp->text_max_length = 0;
thp->text_max_tab_expanded_length = 0;
return;
}
./ ADD NAME=NNMCNRF,SSI=01030011
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@CNRF ")
#pragma csect(static,"NN$CNRF ")
#include "nn.h"
/*** Write to newsrc file. *******************************************/
static Bool
write_to_newsrc(np,newsrc_line,thing)
Rstruc nncb *np;
char *newsrc_line;
char *thing;
{
char *newlinep;
Bool write_ok = TRUE;
if (!*thing) return TRUE;
newlinep = strchr(thing,'\n');
if (newlinep) {
while (newlinep) {
strncat(newsrc_line,thing,newlinep-thing);
if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
write_ok = FALSE;
strcpy(newsrc_line,"");
thing = newlinep + 1;
newlinep = strchr(thing,'\n');
}
strcat(newsrc_line,thing);
return write_ok;
}
if (strlen(newsrc_line) + strlen(thing) > 250) {
if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
write_ok = FALSE;
strcpy(newsrc_line," ");
}
strcat(newsrc_line,thing);
return write_ok;
}
/****** Close NEWSRC file. *******************************************/
void
NNMcnrf(np,what_to_open,updating)
Rstruc nncb *np;
char *what_to_open;
Fool updating;
{
Rstruc newsgroup *gp1;
int newsrc_unread;
int newsrc_topnum;
int newsrc_count;
register int iv;
int read0;
int read1;
int read2;
int read3;
Bool write_ok;
char newsrc_line[257];
char newsrc_numb[32];
write_ok = TRUE;
/* If the file is currently open for input, close it first. */
if (np->newsrc_file) {
if (fclose(np->newsrc_file) < 0) {
fprintf(stderr,"%s: Error closing NEWSRC file\n",what_to_open);
}
np->newsrc_file = NULL;
}
if (!updating) return;
/* Open the file for output. This will empty it at first. */
if (!what_to_open) what_to_open = np->newsrc_to_open;
np->newsrc_file = fopen(what_to_open,"w");
if (np->newsrc_file == NULL) {
perror("Cannot open NEWSRC file");
return;
}
if (np->update_rewriting_newsrc) {
if (!np->batch_mode) {
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLUNRC)");
}
}
/* Write current status into the file. */
/********************************************************************/
/* */
/* Note: The format used here is designed to be compatible with */
/* the format used by ANU-NEWS. This is not an attempt to */
/* duplicate the "look and feel" of ANU-NEWS - it is just */
/* to be compatible with the saved state of VAX NEWS users. */
/* */
/********************************************************************/
/* First record: time of last update in hex, current newsgroup, blah */
if (fprintf(np->newsrc_file,"%.6s %.6s %s\n",
np->lastNGdate, np->lastNGtime,
np->current_newsgroup ? np->current_newsgroup->name : " ")
< 0) write_ok = FALSE;
for (gp1=np->first_newsgroup; gp1; gp1=gp1->next) {
if (!NoSuchGroup(gp1)) { /* Skip groups that don't really exist */
/* for each newsgroup, the following data...
* newsgroupname: (registration) [unread,topnum] read-items
*
* if extended format, topnum = low_number":"high_number
* otherwise topnum = high_number
*/
/* write out gp1->low_number somewhere too? */
newsrc_unread = MAX(gp1->unread_count,0);
newsrc_topnum = gp1->high_number;
newsrc_count = gp1->article_count;
/* The following is a hack for "new newsgroups" */
if (gp1->registered < 0) gp1->registered = 0;
sprintf(newsrc_line,"%s: (%d) [%d,%d]",
/* groupname */ gp1->name,
/* reg/prio */ gp1->registered,
/* unread */ newsrc_unread,
/* topnum */ newsrc_topnum);
/*
* All articles from 1 to low_number - 1 are "read" (expired, etc.)
* If there is an article vector,
* All articles from 1 to vector_first - 1 are "read"
* All articles from vector_last + 1 to high_number are "read"
* end
*/
if (gp1->article_vector == NULL
&& gp1->saved_newsrc_line != NULL) {
strcat(newsrc_line," ");
if (!write_to_newsrc(np,newsrc_line,gp1->saved_newsrc_line))
write_ok = FALSE;
}
else
if (gp1->article_vector == NULL
/* || newsrc_unread == newsrc_count */
|| newsrc_unread == (gp1->vector_last - gp1->vector_first + 1)) {
sprintf(newsrc_numb, " <%d", gp1->low_number - 1);
strcat(newsrc_line, newsrc_numb);
}
else {
read0 = MAX(gp1->vector_first, gp1->low_number);
read1 = 0;
read2 = 0;
read3 = gp1->vector_last;
iv = read0;
if (IsUnread(GETVARK(gp1,iv))) {
sprintf(newsrc_numb, " <%d", read0 - 1);
strcat(newsrc_line, newsrc_numb);
}
while (iv <= read3) {
/* look for the first of a series of read articles */
while (iv <= read3 && IsUnread(GETVARK(gp1,iv))) iv++;
read1 = iv;
/* look for the last of a series of read articles */
while (iv <= read3 && IsRead(GETVARK(gp1,iv))) iv++;
read2 = iv-1;
if (read2 == read3) read2 = gp1->high_number;
if (read1 == read0) sprintf(newsrc_numb," <%d",read2);
else if (read1 > read2) *newsrc_numb = '\0';
else if (read1 == read2) sprintf(newsrc_numb," %d" ,read2);
else if (read1 == read2-1)
sprintf(newsrc_numb," %d %d", read1,read2);
else sprintf(newsrc_numb," |%d=%d",read1,read2);
if (!write_to_newsrc(np,newsrc_line,newsrc_numb))
write_ok = FALSE;
}
}
if (*newsrc_line) {
if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
write_ok = FALSE;
}
}
}
/* Close the file, saving the contents. */
if (!write_ok || ferror(np->newsrc_file)) {
fprintf(stderr,
"%s: Error writing NEWSRC file. Contents may be invalid.\n",
what_to_open);
}
if (fclose(np->newsrc_file) < 0) {
fprintf(stderr,
"%s: Error closing NEWSRC file. Contents may be invalid.\n",
what_to_open);
}
np->newsrc_file = NULL;
return;
}
./ ADD NAME=NNMCONN,SSI=01030039
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@CONN ")
#pragma csect(static,"NN$CONN ")
#include "nn.h"
/****** Internet address formatter. **********************************/
static void
format_ip_address(ia,is)
IPADDRESS ia;
char *is;
{
char *cp = (char *)&ia;
sprintf(is,"%d.%d.%d.%d",*cp,*(cp+1),*(cp+2),*(cp+3));
return;
}
/****** Connect to news server. **************************************/
Bool
NNMconn(np)
Rstruc nncb *np;
{
char *lp;
struct hostent *server_hp;
struct sockaddr_in bindsock; /* socket used by bind */
struct sockaddr_in consock; /* socket used by connect */
int bindsocklen; /* size of bind socket */
int consocklen; /* size of connect socket */
int bindrc; /* the return code from bind */
int connrc; /* the return code from connect */
int ip_part_1;
int ip_part_2;
int ip_part_3;
int ip_part_4;
if (np->connected_to_server) {
NNMdisc(np); /* Disconnect from news server */
}
np->closing_connection = FALSE;
if (!*np->nnserver) {
ERR1("Server not defined;\
An NNTP server name must be defined before a connection can be made."
);
return FALSE;
}
uppercase_in_place(np->nnserver);
/* Get server name and address.
* The client name and address were gotten in NNMmain.
*/
if (strchr(np->nnserver,'.') &&
np->nnserver[strspn(np->nnserver,".0123456789")] == '\0') {
ip_part_1 = ip_part_2 = ip_part_3 = ip_part_4 = 32767;
strcpy(np->server_hostname, np->nnserver);
sscanf(np->nnserver,"%d.%d.%d.%d",&ip_part_1,
&ip_part_2,
&ip_part_3,
&ip_part_4);
if (ip_part_1 > 255 ||
ip_part_2 > 255 ||
ip_part_3 > 255 ||
ip_part_4 > 255) {
ERR2("Syntax error in server network address: %s", np->nnserver);
return FALSE;
}
np->server_ip_address = (IPADDRESS) ((ip_part_1 << 24) +
(ip_part_2 << 16) +
(ip_part_3 << 8) +
(ip_part_4 ));
}
else {
server_hp = gethostbyname(np->nnserver);
if (!server_hp) {
ERR2(
"Unknown host %s - gethostbyname() could not resolve the server name.",
np->nnserver);
return FALSE;
}
strcpy(np->server_hostname, server_hp->h_name);
np->server_ip_address = *(IPADDRESS *)server_hp->h_addr;
}
format_ip_address(np->server_ip_address, np->server_ip_addrstr);
format_ip_address(np->client_ip_address, np->client_ip_addrstr);
if (!np->batch_mode) {
(void)NNMivput(np,"NNSERVER ",np->nnserver,-1);
(void)NNMivput(np,"NNSERVIP ",np->server_ip_addrstr,-1);
(void)NNMivput(np,"NNCLIENT ",np->nnclient,-1);
(void)NNMivput(np,"NNCLIEIP ",np->client_ip_addrstr,-1);
}
consock.sin_family = AF_INET;
consock.sin_port = htons(NNTP_PORT_NUMBER);
consock.sin_addr.s_addr = np->server_ip_address;
bindsock.sin_family = AF_INET;
bindsock.sin_port = 0;
bindsock.sin_addr.s_addr = np->client_ip_address;
np->socknum = socket(AF_INET, SOCK_STREAM, 0);
if (np->socknum < 0) {
REPORT_TCP_ERROR(np->nnserver);
ERR2("TCP/IP error: socket() failed to make socket for server %s.",
np->nnserver);
return FALSE;
}
bindsocklen = sizeof(bindsock);
bindrc = Bind(np->socknum, &bindsock, bindsocklen);
if (bindrc < 0) {
REPORT_TCP_ERROR(np->nnserver);
ERR2("TCP/IP error: bind() failed to bind socket for server %s.",
np->nnserver);
return FALSE;
}
if (np->batch_mode) {
fprintf(np->batch_outfile,
"Client %s (%s) connecting to news server on %s (%s)\n",
np->client_hostname, np->client_ip_addrstr,
np->server_hostname, np->server_ip_addrstr);
}
else {
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLCONN)");
}
if (np->debug_file) {
fprintf(np->debug_file,
"Client %s (%s) connecting to news server on %s (%s)\n",
np->client_hostname, np->client_ip_addrstr,
np->server_hostname, np->server_ip_addrstr);
}
consocklen = sizeof(consock);
connrc = Connect(np->socknum, &consock, consocklen);
if (connrc < 0) {
REPORT_TCP_ERROR(np->nnserver);
ERR2("TCP/IP failure: connect() failed to connect to server %s.",
np->nnserver);
return FALSE;
}
np->connected_to_server = TRUE;
np->time_to_go_home = FALSE;
np->connection_broken = FALSE;
np->xhdr_not_available = FALSE;
/* Now that the connection has been established, the news server
* is trying to send the first message:
* "200 servername blah blah blah - posting allowed"
* or
* "201 servername blah blah blah - no posting allowed"
* or
* "502 servername won't talk to you - goodbye"
* Receive that message. Otherwise disconnect will fail.
*
* Read initial message from server.
*/
for (;;) {
NNMssrvr(np); /* Start server read */
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
switch (np->nntp_message_num) {
case 200: np->posting_allowed = TRUE; break;
case 201: np->posting_allowed = FALSE; break;
case 502: NNMrperr(np); /* Report procotol error */
np->connection_broken = TRUE;
NNMdisc(np); /* Clean up connection */
return FALSE; /* and abandon attempt */
default: NNMrperr(np); /* Report protocol error */
continue; /* and ignore bad data */
}
break;
}
/* Clean up any other responses from server. */
NNMesrvr(np); /* End server read */
/* If server needs authorization, try to provide it. Note that we
* currently do this even on a reconnect. A future optimization
* could be to save the authorization info so that we don't have
* to retrieve it all over again - as long as we don't retain
* sensitive information in memory across ISPF displays.
*/
if (NNMauth(np)) return TRUE; /* Send authinfo */
else return FALSE;
}
./ ADD NAME=NNMCOPY,SSI=01000006
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@COPY ")
#pragma csect(static,"NN$COPY ")
#include "nn.h"
/****** Copy string to non-volatile memory. **************************/
char *
NNMcopy(np,string)
Rstruc nncb *np;
char *string;
{
int len = strlen(string);
char *cp;
/* cheapo one malloc per string right now */
GETMAIN(cp,char,len+1,"copy of string");
if (!cp) return NULL;
strcpy(cp,string);
return cp;
}
./ ADD NAME=NNMDCAN,SSI=01020000
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DCAN ")
#pragma csect(static,"NN$DCAN ")
#include "nn.h"
#define NEWSGROUPS_LENGTH 256-sizeof("Newsgroups: ")
#define SUBJECT_LENGTH 256-sizeof("Subject: ")
#define PATH_LENGTH 256-sizeof("Path: ")
#define FROM_LENGTH 256-sizeof("From: ")
#define APPROVED_LENGTH 256-sizeof("Approved: ")
#define CONTROL_LENGTH 256-sizeof("Control: ")
#define CANCEL_LENGTH 128-sizeof("cancel ")
/*
* Note: The algorithm for determining whether the user can cancel
* an article is:
*
* (1) The article's FROM header must match the user's
* identification - i.e. userid@machine.host
*
* - OR -
*
* (2) if the article has an Approved: header, the user's
* identification must match the Approved: header.
* The assumption is that the Approved: header is the
* ID of the moderator of the newsgroup.
*
*/
/****** Collect additional article headers that we may need. *********/
static void
get_more_headers(np,ap,from,approved)
Rstruc nncb *np;
Rstruc newsarticle *ap;
char *from;
char *approved;
{
struct textline *tp;
struct texthdr *thp;
char *cp;
char *newp;
char *colonp;
int header_index;
char the_header[INTERNET_SIZE];
strcpy(from, "");
strcpy(approved, "");
if (!ap) return;
/* Grovel through headers looking for what we want.
*/
newp = NULL;
thp = &ap->thdr;
strcpy(the_header,"");
for (tp=thp->first_text_line; tp; tp=tp->next) {
if (tp->text[0] == '\0') break;
if (tp->text[0] == ' '
|| tp->text[0] == '\t') {
cp = skip_whitespace(tp->text);
if (*cp == '\0') break;
}
else {
header_index = 0;
colonp = strchr(tp->text,':');
if (!colonp) break;
strcpy(the_header,"");
for (cp = tp->text;cp<colonp;cp++) {
the_header[header_index++] = toupper(*cp);
}
the_header[header_index] = '\0';
cp = skip_whitespace(colonp+1);
}
if (EQUAL(the_header,"FROM"))
strncat(from,cp,FROM_LENGTH);
else if (EQUAL(the_header,"APPROVED"))
strncat(approved,cp,APPROVED_LENGTH);
}
lowercase_and_strip_trailing_in_place(from);
lowercase_and_strip_trailing_in_place(approved);
return;
}
/****** Cancel a news article. ***************************************/
Bool
NNMdcan(np,gp,ap)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Rstruc newsarticle *ap;
{
Bool posted_ok = FALSE;
Bool post_error = FALSE;
int prc;
char *lp;
char *cp;
char *article_check_field;
struct tm *nowtime;
time_t ltime;
char datestr[64];
char midstr [64];
char zuser [9];
char temp [12];
char post_message_id [128];
char post_subject [SUBJECT_LENGTH];
char post_path [PATH_LENGTH];
char post_newsgroups [NEWSGROUPS_LENGTH];
char post_from [FROM_LENGTH];
char post_control [CONTROL_LENGTH];
char post_grape_nuts [CANCEL_LENGTH];
char article_from [FROM_LENGTH];
char article_approved [APPROVED_LENGTH];
(void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
/* assert ap is not null */
strcpy (post_newsgroups, gp->name);
sprintf(post_path, "%s!%s", np->client_hostname, zuser);
sprintf(post_grape_nuts, "cancel %s", ap->message_id);
strcpy (post_subject, post_grape_nuts);
strcpy (post_control, post_grape_nuts);
sprintf(post_from, "%s@%s", zuser, np->client_hostname);
lowercase_in_place(post_from);
get_more_headers(np,ap,article_from,article_approved);
if ((cp=strpbrk(article_from, " \t"))) *cp = '\0';
if ((cp=strpbrk(article_approved, " \t"))) *cp = '\0';
if (*article_approved) article_check_field = article_approved;
else article_check_field = article_from;
if (UNEQUAL(article_check_field, post_from)) {
ERR3("Cancel refused. You, %s, are not %s.",
post_from, article_check_field);
return FALSE;
}
/* Display confirmation panel containing the following info:
*
* newsgroup name = NNCGROUP
* article number = NNCNUM
* article subject = NNCSUBJ
* message ID = NNCMSGID
*/
if (!np->batch_mode) {
sprintf(temp,"%d",ap->number);
(void)NNMivput(np,"NNCGROUP ",gp->name, -1);
(void)NNMivput(np,"NNCNUM ",temp, -1);
(void)NNMivput(np,"NNCSUBJ ",ap->subject, -1);
(void)NNMivput(np,"NNCMSGID ",ap->message_id, -1);
(void)NNMispf(np,"ADDPOP");
(void)NNMispf(np,"DISPLAY PANEL(NNMPCAN)");
prc = np->ispfrc;
(void)NNMispf(np,"REMPOP");
if (prc > 0) { /* see if user pressed END */
WARN1("Operation cancelled, because you pressed END.");
return FALSE;
}
}
/* Start posting here.
*
* Me: POST
* Server: 340 send article to be posted. End with <CR-LF>.<CR-LF>
* or: 440 posting not allowed
* If 430...
*
* See RFC850 for details.
*
* Me: required_header: xxx
* ...
* Me: <null line>
* Me: <text with leading periods hacked>
* Me: .
* Server: 240 article posted OK
* or: 441 posting failed
*/
/* See NNMDPOST for more information. */
/* Get current date and time, and generate a message id from it.
* If the message id is a duplicate, loop around until it isn't.
*/
do {
time(<ime);
nowtime = localtime(<ime);
strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",nowtime);
strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",nowtime);
sprintf(post_message_id, "<%s%s@%s>",
midstr, zuser, np->client_hostname);
} while (EQUAL(post_message_id,np->messageid));
strcpy(np->messageid,post_message_id);
posted_ok = FALSE;
do {
strcpy(np->nntp_command,"POST");
if (!NNMsockt(np)) break; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) break; /* Get server line */
switch (np->nntp_message_num) {
case 340: post_error = FALSE;
break;
case 440: ERR2(
"Cancellation failed. Server %s did not accept the post.",
np->nnserver);
post_error = TRUE;
break;
default: NNMrperr(np); /* Report protocol error */
post_error = TRUE;
break;
}
if (post_error) break;
/* Assert np->server_finished_replying == TRUE
* && np->receiving_text == TRUE
*/
sprintf(np->nntp_command,"Path: %s", post_path);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Newsgroups: %s",post_newsgroups);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Subject: %s",post_subject);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Message-ID: %s", post_message_id);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"From: %s", post_from);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Date: %s", datestr);
if (!NNMsockt(np)) break; /* Send socket command to server */
if (*article_approved) {
sprintf(np->nntp_command,"Approved: %s", article_approved);
if (!NNMsockt(np)) break; /* Send socket command to server */
}
sprintf(np->nntp_command,"Control: %s", post_control);
if (!NNMsockt(np)) break; /* Send socket command to server */
strcpy(np->nntp_command,"");
if (!NNMsockt(np)) break; /* Send socket command to server */
strcpy(np->nntp_command,post_grape_nuts);
if (!NNMsockt(np)) break; /* Send socket command to server */
strcpy(np->nntp_command,".");
if (!NNMsockt(np)) break; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) break; /* Get server line */
switch (np->nntp_message_num) {
case 240: posted_ok = TRUE;
break;
case 441: NNMclrtx(np,NULL); /* Clear text */
NNMouttx(np,np->server_buf,NULL);/* Output text line */
NNMvtx(np,NULL,NULL); /* View text */
ERR2("Cancel failed. Server %s rejected the post.",np->nnserver);
posted_ok = FALSE;
break;
default: NNMrperr(np); /* Report protocol error */
posted_ok = FALSE;
break;
}
NNMesrvr(np); /* End server read */
break;
} while(FALSE); /* one-time DO so I can break out of it */
if (!posted_ok) return FALSE;
WARN4("Cancel request for %s article %d sent to server %s.",
gp->name, ap->number, np->nnserver);
return TRUE;
}
./ ADD NAME=NNMDFAIL,SSI=01000029
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DFAIL")
#pragma csect(static,"NN$DFAIL")
#include "nn.h"
/****** Retrieve allocation failure messages. ************************/
void
NNMdfail(rc,p99)
int rc;
__S99parms *p99;
{
int zero = 0;
unsigned int dfid = 0x40320000;
struct {
short first_level_msg_len;
short first_level_msg_offset;
char first_level_msg[251];
short second_level_msg_len;
short second_level_msg_offset;
char second_level_msg[251];
} dfbuffer;
static int (*ikjeff18_pointer)() = NULL;
#ifndef FETCH
extern int *ikjeff18();
#endif
if (!ikjeff18_pointer) {
#ifdef FETCH
ikjeff18_pointer = (int (*)())fetch("IKJEFF18");
#else
ikjeff18_pointer = (int (*)())ikjeff18;
#endif
}
dfbuffer.first_level_msg_len = 4;
dfbuffer.second_level_msg_len = 4;
if (ikjeff18_pointer) {
if ((*ikjeff18_pointer)(p99,&rc,&zero,&dfid,&zero,&dfbuffer)) {
fprintf(stderr,"IKJEFF18 returned a nonzero return code\n");
}
if (dfbuffer.first_level_msg_len > 0) {
fprintf(stderr,"%*.*s\n",
dfbuffer.first_level_msg_len-4,
dfbuffer.first_level_msg_len-4,
dfbuffer.first_level_msg);
}
if (dfbuffer.second_level_msg_len > 0) {
fprintf(stderr,"%*.*s\n",
dfbuffer.second_level_msg_len-4,
dfbuffer.second_level_msg_len-4,
dfbuffer.second_level_msg);
}
}
else {
#ifdef FETCH
fprintf(stderr,"NNMVS: Cannot fetch IKJEFF18\n");
#else
fprintf(stderr,"Cannot call IKJEFF18, not linked with NNMVS\n");
#endif
}
return;
}
./ ADD NAME=NNMDISC,SSI=01000053
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DISC ")
#pragma csect(static,"NN$DISC ")
#include "nn.h"
/****** Disconnect from news server. *********************************/
void
NNMdisc(np)
Rstruc nncb *np;
{
int closerc;
np->reconnect_in_progress = FALSE;
np->closing_connection = TRUE;
if (np->connection_broken) {
if (np->debug_file) {
fprintf(np->debug_file,
"Client %s (%s) connection with news server on %s (%s) was lost\n",
np->client_hostname, np->client_ip_addrstr,
np->server_hostname, np->server_ip_addrstr);
}
if (np->batch_mode) {
fprintf(np->batch_outfile,
"Client %s (%s) connection with news server on %s (%s) was lost\n",
np->client_hostname, np->client_ip_addrstr,
np->server_hostname, np->server_ip_addrstr);
}
np->connected_to_server = FALSE;
}
else {
np->newsgroup_selected = FALSE;
np->current_newsgroup = NULL;
/* In case of some kind of protocol error, don't let things hang. */
NNMesrvr(np); /* End server read */
if (np->debug_file) {
fprintf(np->debug_file,
"Client %s (%s) disconnecting from news server on %s (%s)\n",
np->client_hostname, np->client_ip_addrstr,
np->server_hostname, np->server_ip_addrstr);
}
if (np->batch_mode) {
fprintf(np->batch_outfile,
"Client %s (%s) disconnecting from news server on %s (%s)\n",
np->client_hostname, np->client_ip_addrstr,
np->server_hostname, np->server_ip_addrstr);
}
else {
(void)NNMivput(np,"NNSOLDER ",np->server_hostname,-1);
(void)NNMivput(np,"NNSOLDIP ",np->server_ip_addrstr,-1);
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLDISC)");
}
/* Send the server a QUIT request. In the past we got away without
* doing this. However, this is important for one reason:
* If the connection was lost before we attempt the disconnect,
* we want to know about it so that we don't attempt the close.
* The best way to find out is to try to send something.
* Fortunately, the protocol fits right in with that need.
*/
strcpy(np->nntp_command,"QUIT");
if (!NNMsockt(np)) return; /* Send socket command to server */
/* In case of some kind of protocol error, don't let things hang. */
NNMesrvr(np); /* End server read */
np->connected_to_server = FALSE;
TCP_DEBUG_ON;
closerc = close(np->socknum);
TCP_DEBUG_OFF;
if (closerc < 0) {
ERR2("TCP/IP error: close() failed to disconnect from server %s.",
np->nnserver);
}
}
return;
}
./ ADD NAME=NNMDISPL,SSI=01000011
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DISPL")
#pragma csect(static,"NN$DISPL")
#include "nn.h"
#ifdef FETCH
#define VL_BIT(X) ((unsigned int)(X) | 0x80000000)
#else
#define VL_BIT(X) (X)
#endif
/****** Display ISPF panel. ******************************************/
int
NNMdispl(np,pan8)
Rstruc nncb *np;
char *pan8;
{
if (np->setmsg) {
np->ispfrc = ISPLINK("DISPLAY ", pan8, VL_BIT("ISRZ002 "));
}
else {
np->ispfrc = ISPLINK("DISPLAY ", VL_BIT(pan8));
}
if (np->ispfrc > 8) NNMierr(np); /* display ISPF error */
np->setmsg = FALSE;
return np->ispfrc;
}
./ ADD NAME=NNMDLANG,SSI=01070041
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DLANG")
#pragma csect(static,"NN$DLANG")
#include "nn.h"
struct nndynarea {
struct newsgroup *newsgroup;
char sel_attr;
char sel_field;
char name_attr;
char name[GROUP_NAME_SIZE];
char count_attr;
int count;
};
/****** Set date and time of last LIST or NEWGROUPS command. *********/
static void
set_date_and_time(np)
Rstruc nncb *np;
{
time_t timeval;
struct tm *now;
time(&timeval);
now = localtime(&timeval);
now->tm_mon++; /* adjust for # of months since Jan. */
sprintf(np->lastNGdate, "%02d%02d%02d",
now->tm_year, now->tm_mon, now->tm_mday);
sprintf(np->lastNGtime, "%02d%02d%02d",
now->tm_hour, now->tm_min, now->tm_sec );
return;
}
/****** Collect newsgroups using list from NEWSGROUPS request. *******/
static Bool
collect_newsgroups(np,just_new_groups)
Rstruc nncb *np;
Fool just_new_groups;
{
Rstruc newsgroup *gp;
struct newsgroup *gpact;
char *lp;
int list_first_article_number = NO_VALUE;
int list_last_article_number = NO_VALUE;
int ac;
char list_posting_allowed = 'n';
char list_name[GROUP_NAME_SIZE] = "";
char formatted_ac[12];
np->sending_text = TRUE;
gpact = NULL;
for (;;) {
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
if (lp == NULL) break;
if (strcmp(lp,".") == 0) break;
if (just_new_groups) {
/* Extract fields from response to "NEWGROUPS" socket request.
Note that only newsgroup names are returned. */
if (1 != sscanf(np->nntp_message_text, "%s", list_name)) {
NNMrbfm(np); /* Report bad format message */
return FALSE;
}
}
else {
/* Extract fields from response to "LIST" socket request.
Note that no article count is provided. */
if (4 != sscanf(np->nntp_message_text, "%s %d %d %c",
list_name,
&list_last_article_number,
&list_first_article_number,
&list_posting_allowed )) {
NNMrbfm(np); /* Report bad format message */
return FALSE;
}
}
if (just_new_groups) {
ac = NO_VALUE;
strcpy(formatted_ac,"");
}
else {
ac = list_last_article_number - list_first_article_number + 1;
sprintf(formatted_ac,"%d",ac);
}
if (!np->batch_mode) {
if (np->update_adding_newsgroups) {
(void)NNMivput(np,"NNLCOUNT ",formatted_ac,-1);
(void)NNMivput(np,"NNLGROUP ",list_name, -1);
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLADDG)");
}
}
gp = NNMaddng(np,list_name); /* Add newsgroup */
if (just_new_groups) {
np->new_newsgroup_count++;
ClearGroupStatus(gp);
SetNewGroup(gp);
gp->registered = -1;
continue;
}
/* Put group in the proper "active file" order */
if (gpact) gpact->next2 = gp;
else np->first_newsgroup_alt = gp;
gp->next2 = NULL;
gpact = gp;
OffNoSuchGroup(gp); /* came from LIST, must exist now */
if (NullGroupStatus(gp)) {
if (np->brand_new_newsrc) {
gp->registered = 0; /* new news user, no autosubscribes */
}
else {
np->new_newsgroup_count++;
SetNewGroup(gp);
gp->registered = -1;
}
}
/*
* Logic:
* This code sets up newsgroups from NNTP LIST.
* They are already found in .newsrc (unless new newsgroups),
* and probably aren't GROUPed yet, but may have been.
* So there is a possibility of an article vector existing,
* but in most cases there won't be.
* The overriding principle here is that the active file knows
* best what's up to date, and is the arbiter of the
* low_number and high_number fields. On the off chance
* that NEWSRC implied different values for these, the
* various adjustments in other routines should handle it.
*/
if (GroupFromNewsrc(gp)
|| GroupFromNNTP(gp)) { /* Adjust unread articles */
NNMadjua(np,gp,ac,list_first_article_number,
list_last_article_number);
}
else {
gp->unread_count = ac;
}
gp->low_number = list_first_article_number;
gp->high_number = list_last_article_number;
gp->article_count = ac;
SetGroupListed(gp);
}
np->dont_reconnect = FALSE;
return TRUE;
}
/****** Display new newsgroups. **************************************/
static Bool
display_new_newsgroups(np,just_new_groups)
Rstruc nncb *np;
Fool just_new_groups;
{
Rstruc newsgroup *gp;
Rstruc nndynarea *dp;
struct nndynarea *nndynarea_address;
int nndynarea_length;
int i;
int prc;
int nnlvl;
int depth;
int depthx80;
int zscrolln;
int topoff;
int dynsize;
char *cp;
char *nndyna;
char *nndyna_slice;
Bool retval;
Bool is_max;
char savechar;
char zverb [9];
char zscrolla [9];
char zcmd [81];
retval = TRUE;
if (np->new_newsgroup_count == 0) return TRUE;
/* Allocate a block of "nndynarea" new-newsgroup structures. */
GETMAIN(nndynarea_address, struct nndynarea,
np->new_newsgroup_count,"nndynarea");
if (!nndynarea_address) return FALSE;
nndynarea_length = np->new_newsgroup_count * sizeof(struct nndynarea);
dp = nndynarea_address;
for (i = 0, gp = np->first_newsgroup; gp; gp = gp->next) {
if (NewGroup(gp)) { /* if new newsgroup */
dp->newsgroup = gp;
strcpy(dp->name,gp->name);
dp->count = gp->article_count;
dp++;
i++;
}
}
if (i != np->new_newsgroup_count) {
fprintf(stderr,
"Possible news server bug: %d new groups but %d NEWGROUPS\n",
i, np->new_newsgroup_count);
}
/* Preinitialize all newsgroups to unsubscribed. */
for (dp = nndynarea_address; i > 0; dp++, i--) {
gp = dp->newsgroup;
gp->registered = 0;
OffNewGroup(gp);
dp->sel_attr = DATAIN_HIGH;
dp->sel_field = ' ';
dp->name_attr = DATAOUT_LOW; /* since all unregistered init'ly */
dp->count_attr = DATAOUT_LOW;
}
/* Display new newsgroups in dynamic area panel. */
(void)NNMispf(np,
"PQUERY PANEL(NNMDNEWG) AREANAME(NNDYNA) DEPTH(NNDEPTH)");
if (np->ispfrc != 0) return FALSE;
depth = NNMiget(np,"NNDEPTH ");
depthx80 = depth * 80;
topoff = 0;
dynsize = 80*(np->new_newsgroup_count + depth) + 1;
GETMAIN(nndyna, char, dynsize+1, "NNDYNA buffer");
if (!nndyna) return FALSE;
memset(nndyna,' ',dynsize);
for (i = 0, cp=nndyna; i < np->new_newsgroup_count; i++, cp+=80) {
dp = &nndynarea_address[i];
memset(cp,' ',80);
cp[ 0] = dp->sel_attr;
cp[ 1] = dp->sel_field;
cp[ 2] = dp->name_attr;
memcpy(&cp[3],dp->name,strlen(dp->name));
if (!just_new_groups) {
cp[62] = dp->count_attr;
sprintf(&cp[63],"%7d article%c",dp->count,
dp->count == 1 ? ' ' : 's');
cp[79] = ' ';
}
}
(void)NNMivput(np,"NNDN1ST ","YES",-1);
do {
(void)NNMivput(np,"ZCMD ","",-1);
(void)NNMivput(np,"NNDYNA ",nndyna+topoff*80,depthx80);
prc = NNMdispl(np,"NNMDNEWG");
if (prc > 8) break;
(void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
if (zcmd[0] == 'Q' /* QUIT */
|| zcmd[0] == 'C') { /* CANCEL */
retval = FALSE;
break;
}
nnlvl = NNMiget(np,"NNLVL ");
nndyna_slice = nndyna + topoff*80;
savechar = nndyna_slice[depthx80];
(void)NNMivget(np,"NNDYNA ",nndyna_slice,depthx80);
nndyna_slice[depthx80] = savechar;
for (i = 0, cp=nndyna_slice; i < nnlvl; i++, cp+=80) {
if (i+topoff >= np->new_newsgroup_count) break;
dp = &nndynarea_address[i+topoff];
gp = dp->newsgroup;
dp->sel_field = ' ';
switch (cp[1]) {
case 'r':
case 'R': gp->registered = 1;
cp[1] = ' ';
cp[2] = DATAOUT_HIGH;
break;
case 'd':
case 'D': gp->registered = 0;
cp[1] = ' ';
cp[2] = DATAOUT_LOW;
break;
case 'q':
case 'Q': NNMqng(np,gp);
cp[1] = ' ';
break;
case ' ': break;
default:
cp[1] = '?';
cp[2] = DATAOUT_LOW;
break;
}
}
(void)NNMivget(np,"ZVERB ",zverb,sizeof(zverb));
(void)NNMivget(np,"ZSCROLLA ",zscrolla,sizeof(zscrolla));
zscrolln = NNMiget(np,"ZSCROLLN ");
is_max = EQUAL(zscrolla,"MAX");
if (EQUAL(zverb,"DOWN")) {
if (is_max) topoff = np->new_newsgroup_count - nnlvl;
else topoff += zscrolln;
}
else if (EQUAL(zverb,"UP")) {
if (is_max) topoff = 0;
else topoff -= zscrolln;
}
if (topoff < 0)
topoff = 0;
if (topoff > np->new_newsgroup_count)
topoff = np->new_newsgroup_count;
} while (prc == 0);
FREEMAIN(nndyna,"NNDYNA buffer");
FREEMAIN(nndynarea_address,"nndynarea");
return retval;
}
/****** Display bogus newsgroups. ************************************/
static Bool
display_bogus_newsgroups(np)
Rstruc nncb *np;
{
Rstruc newsgroup *gp;
Rstruc nndynarea *dp;
struct nndynarea *nndynarea_address;
int nndynarea_length;
int i;
int prc;
int nnlvl;
int depth;
int depthx80;
int zscrolln;
int topoff;
int dynsize;
int bogus_newsgroup_count;
char *cp;
char *k;
char *nndyna;
char *nndyna_slice;
Bool retval;
Bool is_max;
char savechar;
char zverb [9];
char zscrolla [9];
char zcmd [81];
retval = TRUE;
bogus_newsgroup_count = 0;
for (gp = np->first_newsgroup; gp; gp = gp->next) {
if (BogusGroup(gp)) bogus_newsgroup_count++;
}
if (bogus_newsgroup_count == 0) return TRUE;
/* Allocate a block of "nndynarea" new-newsgroup structures. */
GETMAIN(nndynarea_address, struct nndynarea,
bogus_newsgroup_count,"nndynarea");
if (!nndynarea_address) return FALSE;
nndynarea_length = bogus_newsgroup_count * sizeof(struct nndynarea);
dp = nndynarea_address;
for (i = 0, gp = np->first_newsgroup; gp; gp = gp->next) {
if (BogusGroup(gp)) {
SetNoSuchGroup(gp);
OffGroupFromNewsrc(gp);
dp->newsgroup = gp;
strcpy(dp->name,gp->name);
dp++;
}
}
for(dp = nndynarea_address, i=bogus_newsgroup_count; i>0; dp++, i--) {
dp->sel_attr = DATAIN_HIGH;
dp->sel_field = ' ';
dp->name_attr = DATAOUT_LOW; /* since all unregistered init'ly */
}
/* Display bogus newsgroups in dynamic area panel. */
(void)NNMispf(np,
"PQUERY PANEL(NNMDBOGG) AREANAME(NNDYNA) DEPTH(NNDEPTH)");
if (np->ispfrc != 0) return FALSE;
depth = NNMiget(np,"NNDEPTH ");
depthx80 = depth * 80;
topoff = 0;
dynsize = 80*(bogus_newsgroup_count + depth) + 1;
GETMAIN(nndyna, char, dynsize+1, "NNDYNA buffer");
if (!nndyna) return FALSE;
memset(nndyna,' ',dynsize);
for (i = 0, cp=nndyna; i < bogus_newsgroup_count; i++, cp+=80) {
dp = &nndynarea_address[i];
memset(cp,' ',80);
cp[ 0] = dp->sel_attr;
cp[ 1] = dp->sel_field;
cp[ 2] = dp->name_attr;
strncpy(&cp[3],dp->name,67);
if ((k=memchr(&cp[3],'\0',67))) *k = ' ';
cp[70] = DATAOUT_LOW;
memcpy(&cp[71]," ",9);
}
(void)NNMivput(np,"NNDB1ST ","YES",-1);
do {
(void)NNMivput(np,"ZCMD ","",-1);
(void)NNMivput(np,"NNDYNA ",nndyna+topoff*80,depthx80);
prc = NNMdispl(np,"NNMDBOGG");
if (prc > 8) break;
(void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
if (zcmd[0] == 'Q' /* QUIT */
|| zcmd[0] == 'C') { /* CANCEL */
retval = FALSE;
break;
}
nnlvl = NNMiget(np,"NNLVL ");
nndyna_slice = nndyna + topoff*80;
savechar = nndyna_slice[depthx80];
(void)NNMivget(np,"NNDYNA ",nndyna_slice,depthx80);
nndyna_slice[depthx80] = savechar;
for (i = 0, cp=nndyna_slice; i < nnlvl; i++, cp+=80) {
if (i+topoff >= bogus_newsgroup_count) break;
dp = &nndynarea_address[i+topoff];
gp = dp->newsgroup;
dp->sel_field = ' ';
switch (cp[1]) {
case 'd':
case 'D': SetNoSuchGroup(gp);
OffGroupFromNewsrc(gp);
gp->low_number = 0;
gp->high_number = 0;
gp->unread_count = 0;
gp->article_count = 0;
gp->registered = 0;
cp[ 1] = ' ';
cp[ 2] = DATAOUT_LOW;
cp[70] = DATAOUT_HIGH;
memcpy(&cp[71],"Deleted ",9);
break;
case 'k':
case 'K': OffNoSuchGroup(gp);
SetGroupFromNewsrc(gp);
gp->low_number = 0;
gp->high_number = 0;
gp->unread_count = 0;
gp->article_count = 0;
cp[1] = ' ';
cp[70] = DATAOUT_HIGH;
memcpy(&cp[71],"Kept ",9);
break;
case 'q':
case 'Q': NNMqng(np,gp);
cp[1] = ' ';
break;
case ' ':
cp[1] = ' ';
cp[70] = DATAOUT_LOW;
break;
default:
cp[1] = '?';
cp[70] = DATAOUT_HIGH;
memcpy(&cp[71],"What? ",9);
break;
}
}
(void)NNMivget(np,"ZVERB ",zverb,sizeof(zverb));
(void)NNMivget(np,"ZSCROLLA ",zscrolla,sizeof(zscrolla));
zscrolln = NNMiget(np,"ZSCROLLN ");
is_max = EQUAL(zscrolla,"MAX");
if (EQUAL(zverb,"DOWN")) {
if (is_max) topoff = bogus_newsgroup_count - nnlvl;
else topoff += zscrolln;
}
else if (EQUAL(zverb,"UP")) {
if (is_max) topoff = 0;
else topoff -= zscrolln;
}
if (topoff < 0)
topoff = 0;
if (topoff > bogus_newsgroup_count)
topoff = bogus_newsgroup_count;
} while (prc == 0);
FREEMAIN(nndyna,"NNDYNA buffer");
FREEMAIN(nndynarea_address,"nndynarea");
return retval;
}
/****** Option.....list all new newsgroups. **************************/
static Bool
list_new(np)
Rstruc nncb *np;
{
char *lp;
char mmddyy[9];
char hhmmss[9];
lp = np->lastNGdate + strspn(np->lastNGdate,"0");
if (*lp == '\0') {
ERR1(
"There is no previous date in the NEWSRC file. Select the List option."
);
return FALSE;
}
sprintf(np->nntp_command, "NEWGROUPS %.6s %.6s",
np->lastNGdate, np->lastNGtime);
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
sprintf(mmddyy,"%2.2s/%2.2s/%2.2s",
&np->lastNGdate[2], &np->lastNGdate[4], &np->lastNGdate[0]);
sprintf(hhmmss,"%2.2s:%2.2s:%2.2s",
&np->lastNGtime[0], &np->lastNGtime[2], &np->lastNGtime[4]);
if (np->update_adding_newsgroups) {
if (!np->batch_mode) {
(void)NNMivput(np,"NNNGDT ",mmddyy,-1);
(void)NNMivput(np,"NNNGTM ",hhmmss,-1);
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLNEWG)");
}
}
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
if (np->nntp_message_num != 231) NNMrperr(np);
if (!collect_newsgroups(np,TRUE)) return FALSE;
if (np->batch_mode) return TRUE;
if (!display_new_newsgroups(np,TRUE)) return FALSE;
set_date_and_time(np);
if (np->new_newsgroup_count == 0) {
ERR3(
"No new newsgroups since last use of L or N option, on %s %s",
mmddyy, hhmmss);
return FALSE;
}
return TRUE;
}
/****** Option.....list all known newsgroups. ************************/
static Bool
list_all(np)
Rstruc nncb *np;
{
char *lp;
strcpy(np->nntp_command,"LIST");
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
if (!np->batch_mode) {
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLLIST)");
}
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
if (np->nntp_message_num != 215) NNMrperr(np);
if (!collect_newsgroups(np,FALSE)) return FALSE;
if (np->batch_mode) return TRUE;
if (!display_new_newsgroups(np,FALSE)) return FALSE;
if (!display_bogus_newsgroups(np)) return FALSE;
set_date_and_time(np);
np->new_newsgroup_count = 0;
np->show_all_newsgroups = TRUE;
return NNMvng(np); /* View newsgroups */
}
/****** Fake disconnect. ********************************************/
static void
fake_disconnect(np)
Rstruc nncb *np;
{
char *dummy = "503 Simulated disconnect.";
int index;
/* fake a disconnect condition by sending an NNTP "QUIT".
* The next attempt to communicate with the socket will get
* the simulated response instead of what it expected.
*/
strcpy(np->nntp_command,"QUIT");
if (!NNMsockt(np)) return; /* Send socket command to server */
index = strlen(dummy);
strcpy(np->g_buf+1,dummy);
np->g_buf[index+1] = CARRIAGE_RETURN;
np->g_buf[index+2] = LINE_FEED;
np->g_bytes_returned = index+3;
np->g_buf_index = 0;
return;
}
/****** List all or new groups. **************************************/
Bool
NNMdlang(np,option)
Rstruc nncb *np;
enum list_option option;
{
/* Since an attempt to reconnect while reading data from the server
* will leave the news reader in an inconsistent state and possibly
* lead to destroyed newsrc file, we suppress all attempts to do an
* automatic reconnection while this is in progress.
*/
np->dont_reconnect = TRUE;
switch (option) {
case LIST_ALL: return list_all(np);
case LIST_NEW: return list_new(np);
case LIST_ALL_DISCONNECT:
fake_disconnect(np);
return list_all(np);
}
np->dont_reconnect = FALSE;
}
./ ADD NAME=NNMDMAIL,SSI=01020048
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DMAIL")
#pragma csect(static,"NN$DMAIL")
#include "nn.h"
#define TO_LENGTH 256-sizeof("To: ")
#define SUBJECT_LENGTH 256-sizeof("Subject: ")
#define FROM_LENGTH 256-sizeof("From: ")
#define REPLY_TO_LENGTH 256-sizeof("Reply-to: ")
/****** Determine to whom to reply, according to RFC822 standards ****/
static char *
to_whom_to_reply(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
struct textline *tp;
struct texthdr *thp;
char *cp;
char *colonp;
char *resent_reply_to = NULL;
char *resent_from = NULL;
char *reply_to = NULL;
char *from = NULL;
char *resent_sender = NULL;
char *sender = NULL;
int header_index;
char the_header[INTERNET_SIZE];
if (!ap) return "";
/* Since RFC1036 (Standard for Interchange of USENET Messages)
* seems to imply that RFC822 header format is OK, we would
* expect to do this. In reality, headers like Reply-to: are
* often filled with the name of the mailing list (e.g. BITNET).
* Therefore, the user needs to have the option of using
* the From: header for replies. Anyhow...
*/
/* Grovel through headers looking for likely candidates. The official
* pecking order is:
*
* Resent-Reply-To:
* Resent-From:
* Reply-To:
* From:
* Resent-Sender:
* Sender:
*
* If none of the above, punt by returning a null string.
*
* NOTE: There is no provision in this code for continued headers.
* If you want to handle continued headers, use the code in
* NNMDPOST as a model. You will have to allocate your own
* storage to hold 'em.
*/
thp = &ap->thdr;
strcpy(the_header,"");
for (tp=thp->first_text_line; tp; tp=tp->next) {
if (tp->text[0] == '\0') break;
if (tp->text[0] == ' '
|| tp->text[0] == '\t') {
cp = skip_whitespace(tp->text);
if (*cp == '\0') break;
}
else {
header_index = 0;
colonp = strchr(tp->text,':');
if (!colonp) break;
strcpy(the_header,"");
for (cp = tp->text;cp<colonp;cp++) {
the_header[header_index++] = toupper(*cp);
}
the_header[header_index] = '\0';
}
cp = skip_whitespace(colonp+1);
if (!strcmp(the_header,"RESENT-REPLY-TO")) resent_reply_to = cp;
else if (!strcmp(the_header,"RESENT-FROM" )) resent_from = cp;
else if (!strcmp(the_header,"REPLY-TO" )) reply_to = cp;
else if (!strcmp(the_header,"FROM" )) from = cp;
else if (!strcmp(the_header,"RESENT-SENDER" )) resent_sender = cp;
else if (!strcmp(the_header,"SENDER" )) sender = cp;
}
return (resent_reply_to ? resent_reply_to :
resent_from ? resent_from :
reply_to ? reply_to :
from ? from :
resent_sender ? resent_sender :
sender ? sender :
"");
}
/****** Reply to a news article by mail, or just mail a message ******/
void
NNMdmail(np,gp,ap)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Rstruc newsarticle *ap;
{
Bool filled = FALSE;
Bool edit_error = FALSE;
Bool mail_error = FALSE;
int l;
int display_rc;
FILE *efp = NULL;
FILE *mfp = NULL;
FILE *sfp = NULL;
struct tm *now;
char *cp;
time_t ltime;
char datestr [64];
char midstr [64];
char zuser [ 9];
char tempdsn [L_tmpnam];
char outpdsn [L_tmpnam];
char editstr [40+L_tmpnam];
char edit_profile [ 9];
char signature_file [ 64];
char mail_message_id [128];
char zcmd [ 81];
char nnmailfr [FROM_LENGTH];
char nnmailrt [REPLY_TO_LENGTH];
char mail_from [FROM_LENGTH];
char mail_to [TO_LENGTH];
char mail_subject [SUBJECT_LENGTH];
char mailline [260];
char sigline [260];
char mail_command [260];
(void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
if (ap) {
if (strlen(ap->subject) >= 3 &&
(!memcmp(ap->subject,"Re:",3) ||
!memcmp(ap->subject,"re:",3) ||
!memcmp(ap->subject,"RE:",3))) strcpy(mail_subject,"");
else strcpy(mail_subject,"Re: ");
strncat(mail_subject, ap->subject, sizeof(mail_subject));
}
else strcpy(mail_subject,"");
(void)NNMivput(np,"NNMAILTO ",to_whom_to_reply(np,ap),-1);
(void)NNMivput(np,"NNMAILOT ",(ap ? ap->from : "") ,-1);
(void)NNMivput(np,"NNMAILSJ ",mail_subject,-1);
strcpy(outpdsn,"");
/* Can't use this - C/370 compiler bug... */
/* strcpy(tempdsn,ap ? "" : np->maildsn); */
if (ap) strcpy(tempdsn,"");
else strcpy(tempdsn,np->maildsn);
if (!*tempdsn) {
if (!tmpnam(tempdsn)) {
ERR1(
"A temporary data set name could not be created. tmpnam() error.");
return;
}
if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
ERR2("Error trying to open temp data set: %s", tempdsn);
return;
}
if (fclose(efp) < 0) {
ERR2("Error trying to close temp data set: %s", tempdsn);
return;
}
efp = NULL;
if (!ap) strcpy(np->maildsn,tempdsn);
}
while (NNMdispl(np,"NNMQMAIL") == 0) {
NNMivget(np,"NNMAILTO ",mail_to, sizeof(mail_to) );
NNMivget(np,"NNMAILSJ ",mail_subject, sizeof(mail_subject) );
NNMivget(np,"NNMAILRT ",nnmailrt, sizeof(nnmailrt) );
NNMivget(np,"NNMAILFR ",nnmailfr, sizeof(nnmailfr) );
NNMivget(np,"NNMAILSF ",signature_file, sizeof(signature_file) );
NNMivget(np,"NNEDPROF ",edit_profile, sizeof(edit_profile) );
(void)NNMivput(np,"NNTEMPDS ",tempdsn,-1);
/* Insure that we can access the signature file, if given. */
if (*signature_file) {
if (!(sfp=fopen(signature_file,"r"))) {
perror(signature_file);
ERR2("Cannot open signature file %s. Check that it is valid.",
signature_file);
continue;
}
}
else sfp = NULL;
/* Fill temporary data set with message to which we are replying,
* if this is a REPLY request,
* and the contents of the signature file if any.
*/
if (!filled) {
if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
ERR2("Error trying to open temp data set: %s", tempdsn);
continue;
}
if (ap) {
np->extract_file = efp;
np->extract_appending = FALSE;
np->extract_separator_line = FALSE;
np->extract_tab_expanding = TRUE;
np->following_up = TRUE;
fprintf(efp, "In article %s,\n%s writes:\n\n",
ap->message_id, ap->from);
(void)NNMxtx(np,ap,FALSE); /* Extract article text */
np->following_up = FALSE;
if (ferror(efp)) {
ERR2("Error trying to write to temp data set: %s", tempdsn);
continue;
}
}
if (sfp) {
fprintf(efp,"\n--\n",efp);
if (ferror(efp)) np->extract_write_error = TRUE;
for (;;) {
fgets(sigline,sizeof(sigline),sfp);
if (ferror(sfp)) {
ERR2(
"Cannot read from signature file %s. Check that it is valid.",
signature_file);
break;
}
if (feof(sfp)) break;
if ((cp=strchr(sigline,'\n'))) *cp = '\0';
l = strlen(sigline);
fwrite(sigline,(l>251 ? 251 : l),1,efp);
if (ferror(efp)) {
np->extract_write_error = TRUE; break;
}
if (fputc('\n',efp) == EOF) {
np->extract_write_error = TRUE; break;
}
}
(void)fclose(sfp);
if (ferror(efp)) {
ERR2("Error trying to write to temp data set: %s", tempdsn);
continue;
}
}
if (fclose(efp) < 0) {
ERR2("Error trying to close temp data set: %s", tempdsn);
continue;
}
filled = TRUE;
}
efp = NULL;
#ifndef I370
sprintf(editstr,"EDIT DATASET(%s) PROFILE(%s)",tempdsn,edit_profile);
#else
sprintf(editstr, "EDIT DATASET('%s') PROFILE(%s)",
tempdsn+4, edit_profile);
#endif
edit_error = FALSE;
(void)NNMispf(np,editstr);
switch (np->ispfrc) {
case 0: edit_error = FALSE; break;
case 4: ERR1(
"Edit ended without SAVE, mailing cancelled. Reenter and SAVE to mail."
); continue;
default: edit_error = TRUE; break;
}
if (edit_error) continue;
/* Confirm mailing. */
(void)NNMispf (np,"ADDPOP ");
display_rc = NNMdispl(np,"NNMPCONM");
(void)NNMispf (np,"REMPOP ");
(void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
if (display_rc > 0) continue;
if (*zcmd == 'c' || *zcmd == 'C') {
(void)NNMivput(np,"ZCMD ","",-1);
ERR1("Mailing cancelled by user. Reenter EDIT and SAVE to mail.");
return;
}
if (!(efp = fopen(tempdsn,"r"))) {
ERR2("Error trying to open temp data set: %s", tempdsn);
continue;
}
/* Get current date and time, and generate a message id from it.
* If the message id is a duplicate, loop around until it isn't.
*/
do {
time(<ime);
now = localtime(<ime);
strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",now);
strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S", now);
sprintf(mail_message_id,"<%s%s@%s>",
midstr, zuser, np->client_hostname);
} while (EQUAL(mail_message_id,np->messageid));
strcpy(np->messageid,mail_message_id);
if (!*outpdsn) {
if (!tmpnam(outpdsn)) {
ERR1(
"A temporary data set name could not be created. tmpnam() error."
);
continue;
}
}
if (!(mfp = OPEN_TEXT_FILE_FOR_WRITE(outpdsn))) {
ERR2("Error trying to open temp data set: %s", outpdsn);
continue;
}
do {
if (*nnmailfr)
sprintf(mail_from,"%s@%s (%s)",
zuser, np->client_hostname, nnmailfr);
else sprintf(mail_from,"%s@%s",
zuser, np->client_hostname);
fprintf(mfp,"From: %s\n", mail_from);
fprintf(mfp,"To: %s\n", mail_to);
fprintf(mfp,"Subject: %s\n", mail_subject);
fprintf(mfp,"Date: %s\n", datestr);
fprintf(mfp,"Message-ID: %s\n", mail_message_id);
/* insert optional headers here */
if (*nnmailrt) {
fprintf(mfp,"Reply-to: %s\n", nnmailrt);
}
fprintf(mfp,"Sender: MVS NNTP News Reader <%s@%s>\n",
NNMVS_NAME, np->client_hostname);
if (ap) {
/*
* Uncomment this section when a references field in the
* newsarticle struct is added. Will require total recompilation
*
* if (ap->references)
* sprintf(np->nntp_command,"References: %s %s\n",
* ap->references, ap->message_id);
* else
*/
fprintf(mfp,"References: %s\n",ap->message_id);
}
/* By rights the following should be a null line.
* However, C/370 always makes it a single blank anyhow,
* and even if it were a null line (as SAS/C does),
* UCLA/MAIL would break. Hence, make it a single blank.
*/
fprintf(mfp," \n");
while (!feof(efp) && !ferror(efp)) {
fgets(mailline,sizeof(mailline),efp);
if (feof(efp)) break;
if (ferror(efp)) break;
if (*mailline && mailline[l=strlen(mailline)-1] == '\n')
mailline[l] = '\0';
fprintf(mfp,"%s\n",mailline);
}
fclose(mfp);
#ifndef I370
sprintf(mail_command,"NNMMAIL %s %s",outpdsn,mail_to);
#else
sprintf(mail_command,"NNMMAIL '%s' %s",outpdsn+4,mail_to);
#endif
if (NNMtso(mail_command) != 0) {
ERR1("Mail failed. Failure trying to send your message.");
mail_error = TRUE;
}
remove(outpdsn);
break;
} while(FALSE); /* one-time DO so I can break out of it */
if (!mail_error) {
(void)NNMivput(np,"NNMAILID ",mail_message_id,-1);
WARN1("Your mail message has been sent, presumably successfully.");
break;
}
}
if (!efp) return;
if (ferror(efp)) {
ERR2("Error trying to read from temp data set: %s", tempdsn);
}
if (fclose(efp) < 0) {
ERR2("Error trying to close temp data set: %s", tempdsn);
}
if (ap) {
if (remove(tempdsn) < 0) {
ERR2("Error trying to delete temp data set: %s", tempdsn);
}
}
return;
}
./ ADD NAME=NNMDMENU,SSI=01010000
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DMENU")
#pragma csect(static,"NN$DMENU")
#include "nn.h"
/****** Report invalid or unsupported selection. *********************/
static Bool
display_invalid_selection(np)
Rstruc nncb *np;
{
ERR1("Your selection is not valid. Please choose an available one.");
return FALSE;
}
/****** Option.....set user options. *********************************/
static Bool
display_set_options(np)
Rstruc nncb *np;
{
NNMdsopt(np,NULL);
return FALSE;
}
/****** Option.....execute NNTP commands. ****************************/
static Bool
display_nntp(np)
Rstruc nncb *np;
{
NNMdnntp(np,NULL);
return FALSE;
}
/****** Option.....list ALL newsgroups from NEWSRC file. *************/
static Bool
display_all_from_newsrc(np)
Rstruc nncb *np;
{
if (np->newsgroup_order == NNTP_LIST_ORDER)
np->newsgroup_order = ALPHABETICAL_ORDER;
np->show_all_newsgroups = TRUE;
return NNMvng(np); /* View newsgroups */
}
/****** Option.....list REGISTERED newsgroups from NEWSRC file. ******/
static Bool
display_reg_from_newsrc(np)
Rstruc nncb *np;
{
char nnrgans[4];
int prc;
Rstruc newsgroup *gp;
struct countdown cd;
/* Before viewing the newsgroup list, go through all the newsgroups
* and get the status of each one by selecting it.
* This is controlled by the NNREGNNG variable if an option was
* preselected and Y or N was specified for REGISTERSTATUS.
*/
nnrgans[0] = 'P';
if (np->preselection) {
switch (np->nnregnng[0]) {
case 'N': nnrgans[0] = 'N'; break;
case 'Y': nnrgans[0] = 'Y'; break;
}
}
if (nnrgans[0] == 'P') {
/* Display panel asking if user really wants to do this. */
(void)NNMispf(np,"ADDPOP");
prc = NNMdispl(np,"NNMPGREG");
(void)NNMispf(np,"REMPOP");
if (prc > 0) return FALSE; /* see if user pressed END */
(void)NNMivget(np,"NNRGANS ",nnrgans,sizeof(nnrgans));
}
if (nnrgans[0] == 'Y') {
if (np->updatefreq >= 0) {
cd.do_update = TRUE;
cd.done = 0;
cd.to_do = 0;
for (gp=np->first_newsgroup;gp;gp=gp->next) {
if (gp->registered) cd.to_do++;
}
}
for (gp=np->first_newsgroup;gp;gp=gp->next) {
if (gp->registered) {
if (np->updatefreq >= 0) {
(void)NNMivput(np,"NNLGROUP ",gp->name,-1);
/*
* (void)NNMispf(np,"CONTROL DISPLAY LOCK");
* (void)NNMispf(np,"DISPLAY PANEL(NNMLRETG)");
*/
NNMupdt(np,&cd,np->updatefreq > 0 ? "NNMLRET2" : "NNMLRET3");
}
NNMdng(np,gp,NULL); /* do newsgroup by address */
}
}
}
if (np->newsgroup_order == NNTP_LIST_ORDER)
np->newsgroup_order = ALPHABETICAL_ORDER;
np->show_all_newsgroups = FALSE;
return NNMvng(np); /* View newsgroups */
}
/****** Option.....list all newsgroups. ******************************/
static Bool
list_all_newsgroups(np)
Rstruc nncb *np;
{
return NNMdlang(np,LIST_ALL);
}
/****** Option.....list all newsgroups with fake disconnect. *********/
static Bool
list_all_newsgroups_with_fake_disconnect(np)
Rstruc nncb *np;
{
return NNMdlang(np,LIST_ALL_DISCONNECT);
}
/****** Option.....list new newsgroups. ******************************/
static Bool
list_new_newsgroups(np)
Rstruc nncb *np;
{
return NNMdlang(np,LIST_NEW);
}
/****** Option.....retrieve articles from specified newsgroup. *******/
static Bool
display_specific_newsgroup(np)
Rstruc nncb *np;
{
Rstruc newsgroup *gp;
np->newsgroup_selected = FALSE;
/* The ISPF variable NNGROUPI contains the name of the newsgroup. */
if (NNMivget(np,"NNGROUPI ",np->nngroup,sizeof(np->nngroup))) {
lowercase_in_place(np->nngroup);
(void)NNMivput(np,"NNGROUP ",np->nngroup,-1);
gp = NNMdng(np,NULL,np->nngroup); /* do newsgroup by name */
if (!gp) {
(void)NNMivput(np,"NNCURSOR ","NNGROUPI ",8);
return FALSE;
}
np->show_all_articles = TRUE;
np->bypass_header_retrieval = FALSE;
np->unread_articles_only = FALSE;
(void)NNMvar(np,gp); /* View articles */
}
return TRUE;
}
/****** Display menu. ************************************************/
enum display_retval
NNMdmenu(np,selfunp)
Rstruc nncb *np;
Bool (**selfunp)();
{
char zcmd[72];
char new_nnserver[MAXHOSTNAMELEN];
Bool server_changed = FALSE;
*selfunp = NULL;
if (np->preselection) {
zcmd[0] = toupper(np->preselection);
np->preselection = SELECTION_EXIT;
(void)NNMispf(np,
"VGET (NNSERVER NNNEWSRC NNREGNNG NNGROUPI) PROFILE");
}
else {
(void)NNMispf(np,"CONTROL DISPLAY REFRESH");
(void)NNMdispl(np,"NNM ");
if (np->ispfrc > 8) return DISPLAY_FAILURE;
if (np->ispfrc > 0) return DISPLAY_EXIT;
if (!NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd))) return DISPLAY_ERROR;
}
if (!NNMivget(np,"NNSERVER ",new_nnserver,MAXHOSTNAMELEN)
|| !NNMivget(np,"NNREGNNG ",np->nnregnng,sizeof(np->nnregnng))) {
np->preselection = '\0';
return DISPLAY_ERROR;
}
/* Note: selection functions return Bool value indicating whether
* to rewrite NEWSRC file (TRUE) or not (FALSE).
* See NNMMAIN for implementation of this.
*/
switch (zcmd[0]) {
case SELECTION_ALL: *selfunp = display_all_from_newsrc; break;
case SELECTION_REG: *selfunp = display_reg_from_newsrc; break;
case SELECTION_GROUP: *selfunp = display_specific_newsgroup; break;
case SELECTION_LIST: *selfunp = list_all_newsgroups; break;
case SELECTION_NEWG: *selfunp = list_new_newsgroups; break;
case SELECTION_NNTP: *selfunp = display_nntp; break;
case SELECTION_OPTS: *selfunp = display_set_options; break;
case SELECTION_EXIT: return DISPLAY_EXIT;
case SELECTION_LIST_DISCONNECT:
*selfunp = list_all_newsgroups_with_fake_disconnect;
break;
default: *selfunp = display_invalid_selection;
np->preselection = '\0';
return DISPLAY_REPEAT;
};
/* If user typed a different server name, or this is the first time,
connect to the requested server. */
if (UNEQUAL(new_nnserver,np->nnserver)) {
server_changed = TRUE;
}
if (!np->connected_to_server || np->connection_broken ||
server_changed) {
strcpy(np->nnserver,new_nnserver);
if (!NNMconn(np)) { /* Connect to news server */
(void)NNMivput(np,"NNCURSOR ","NNSERVER ",8);
*selfunp = NULL;
np->preselection = '\0';
return DISPLAY_ERROR;
}
}
return DISPLAY_REPEAT;
}
./ ADD NAME=NNMDNG,SSI=010F0052
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DNG ")
#pragma csect(static,"NN$DNG ")
#include "nn.h"
/****** Process newsgroup by name or address. ************************/
struct newsgroup *
NNMdng(np,gp,group)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *group;
{
int group_article_count = NO_VALUE;
int group_first_article_number = NO_VALUE;
int group_last_article_number = NO_VALUE;
char group_name[GROUP_NAME_SIZE] = "";
/* Tell the server to select the requested newsgroup. */
if (!NNMestng(np,gp ? gp->name : group)) /* Establish newsgroup */
return NULL;
/* From the response to the "GROUP xxx" NNTP selection request,
extract the number of articles and the numbers of the
first and last articles, as well as the actual name. */
if (4 != sscanf(np->nntp_message_text, "%d %d %d %s",
&group_article_count,
&group_first_article_number,
&group_last_article_number,
group_name)) {
NNMrbfm(np); /* Report bad format message */
return NULL;
}
lowercase_in_place(group_name);
if (!gp) gp = NNMaddng(np,group_name); /* Add newsgroup */
OffNoSuchGroup(gp);
OffGroupError(gp);
/* Logic:
* This code sets up a newsgroup from NNTP GROUP.
* They are already found in .newsrc (unless new newsgroups),
* and may or may not have already been LISTed.
* So there is a possibility of an article vector existing,
* but in most cases there won't be.
* The overriding principle here is that the active file knows
* best the actual range, but the GROUP command will return
* information about missing articles at either end of the list.
*/
if (GroupFromNewsrc(gp)
|| GroupFromNNTP(gp)) { /* Adjust unread articles */
NNMadjua(np,gp,group_article_count,
group_first_article_number,
group_last_article_number);
}
else {
gp->unread_count = group_article_count;
}
/* Allocate article vector */
NNMallav(np,gp,group_first_article_number,group_last_article_number);
gp->article_count = group_article_count;
if (gp->article_vector) {
if (gp->low_number == 0
|| gp->low_number > group_first_article_number
|| !GroupFromNNTP(gp)) {
gp->low_number = group_first_article_number;
}
if (gp->high_number == 0
|| gp->high_number < group_last_article_number) {
gp->high_number = group_last_article_number;
}
}
/*
*
* Don't know why this was here, but it is causing a bug with
* registering new groups, so take it out.
*
* if (!GroupFromNewsrc(gp)) {
* gp->registered = 0;
* }
*/
if (np->show_all_articles) SetGroupSelected(gp);
else SetGroupSelectedUnread(gp);
return gp;
}
./ ADD NAME=NNMDNNTP,SSI=01000015
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DNNTP")
#pragma csect(static,"NN$DNNTP")
#include "nn.h"
/****** Option ... process native NNTP protocol commands. ************/
void
NNMdnntp(np,command)
Rstruc nncb *np;
char *command;
{
if (command && *command) {
strncpy(np->nntp_command, command, CLIENT_BUF_MSGSIZE);
NNMnntp(np); /* execute NNTP commands */
}
else while (NNMdispl(np,"NNM0 ") == 0 && !np->quit) {
(void)NNMivget(np,"NNCMD ",np->nntp_command,CLIENT_BUF_MSGSIZE);
if (np->ispfrc == 0) NNMnntp(np); /* execute NNTP commands */
if (np->quit) break;
}
return;
}
./ ADD NAME=NNMDOIT,SSI=01040002
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DOIT ")
#pragma csect(static,"NN$DOIT ")
#include "nn.h"
/****** Do it (whatever it is) to the article. ***********************/
void
NNMdoit(np,ap,whatfor)
Rstruc nncb *np;
Rstruc newsarticle *ap;
Fool whatfor;
{
Rstruc newsgroup *gp;
VARK *vp;
gp = np->current_newsgroup;
vp = &GETVARK(gp,ap->number);
switch (whatfor) {
case 'S':
NNMvtx(np,gp,ap); /* View text */
NNMmarr(np,gp,vp); /* Make article read */
ap->action = READ;
break;
case 'E':
np->extract_write_error = FALSE;
np->extract_close_error = FALSE;
np->printing = FALSE;
if (NNMxtx(np,ap,TRUE)) { /* Extract text */
if (!np->extract_write_error &&
!np->extract_close_error) {
NNMmarr(np,gp,vp); /* Make article read */
ap->action = EXTRACTED;
}
}
break;
case 'P':
np->extract_write_error = FALSE;
np->extract_close_error = FALSE;
np->printing = TRUE;
if (NNMxtx(np,ap,TRUE)) { /* Print text */
if (!np->extract_write_error &&
!np->extract_close_error) {
NNMmarr(np,gp,vp); /* Make article read */
ap->action = PRINTED;
}
}
break;
case 'F':
NNMdpost(np,gp,ap); /* Post followup */
ap->action = RETRIEVED;
break;
case 'R':
NNMdmail(np,gp,ap); /* Mail reply */
ap->action = RETRIEVED;
break;
case 'C':
if (NNMdcan(np,gp,ap)) { /* Cancel article */
ap->action = CANCELLED;
}
break;
}
np->top_article = ap->number;
np->top_sorted_article = np->current_sortvark;
return;
}
./ ADD NAME=NNMDPOST,SSI=01010016
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DPOST")
#pragma csect(static,"NN$DPOST")
#include "nn.h"
#define NEWSGROUPS_LENGTH 256-sizeof("Newsgroups: ")
#define SUBJECT_LENGTH 256-sizeof("Subject: ")
#define PATH_LENGTH 256-sizeof("Path: ")
#define FROM_LENGTH 256-sizeof("From: ")
#define REPLY_TO_LENGTH 256-sizeof("Reply-to: ")
#define FOLLOWUP_TO_LENGTH 256-sizeof("Followup-to: ")
#define HEADCAT(A,B) strncat((A),(B),NEWSGROUPS_LENGTH)
/****** Make a comma delimited list out of user's newsgroup spec. ****/
static void
make_comma_delimited_list(instring,outstring)
char *instring;
char *outstring;
{
char *icp;
char *ocp;
Bool between;
between = FALSE;
icp = instring + strspn(instring," ,");
ocp = outstring;
do {
switch (*icp) {
case '\0': *ocp = '\0'; break;
case ' ' :
case ',' : between = TRUE; break;
default : if (between) {
between = FALSE;
*(ocp++) = ',';
}
*(ocp++) = tolower(*icp);
break;
}
} while (*icp++);
}
/****** Collect additional article headers that we may need. *********/
static void
get_more_headers(np,ap,newsgroups,followup_to)
Rstruc nncb *np;
Rstruc newsarticle *ap;
char *newsgroups;
char *followup_to;
{
struct textline *tp;
struct texthdr *thp;
char *cp;
char *newp;
char *colonp;
int header_index;
char the_header[INTERNET_SIZE];
strcpy(newsgroups, "");
strcpy(followup_to, "");
if (!ap) return;
/* Grovel through headers looking for what we want. */
newp = NULL;
thp = &ap->thdr;
strcpy(the_header,"");
for (tp=thp->first_text_line; tp; tp=tp->next) {
if (tp->text[0] == '\0') break;
if (tp->text[0] == ' '
|| tp->text[0] == '\t') {
cp = skip_whitespace(tp->text);
if (*cp == '\0') break;
}
else {
header_index = 0;
colonp = strchr(tp->text,':');
if (!colonp) break;
strcpy(the_header,"");
for (cp = tp->text;cp<colonp;cp++) {
the_header[header_index++] = toupper(*cp);
}
the_header[header_index] = '\0';
cp = skip_whitespace(colonp+1);
}
if (EQUAL(the_header,"NEWSGROUPS" )) HEADCAT(newsgroups, cp);
else if (EQUAL(the_header,"FOLLOWUP-TO" )) HEADCAT(followup_to,cp);
}
lowercase_and_strip_trailing_in_place(newsgroups);
lowercase_and_strip_trailing_in_place(followup_to);
return;
}
/****** Post a news article. *****************************************/
void
NNMdpost(np,gp,ap)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Rstruc newsarticle *ap;
{
Bool filled = FALSE;
Bool edit_error = FALSE;
Bool post_error = FALSE;
int l;
int display_rc;
char *postdefault = NULL;
char *lp;
char *cp;
FILE *efp = NULL;
FILE *sfp = NULL;
struct tm *now;
time_t ltime;
char datestr [64];
char midstr [64];
char zuser [ 9];
char temp [12];
char tempdsn [L_tmpnam];
char editstr [40+L_tmpnam];
char edit_profile [ 9];
char signature_file [ 64];
char post_message_id [128];
char zcmd [ 81];
char post_subject [SUBJECT_LENGTH];
char post_path [PATH_LENGTH];
char post_newsgroups [NEWSGROUPS_LENGTH];
char post_followup_to [NEWSGROUPS_LENGTH];
char post_from [FROM_LENGTH];
char nnpostng [NEWSGROUPS_LENGTH];
char nnpostrt [REPLY_TO_LENGTH];
char nnpostfo [FOLLOWUP_TO_LENGTH];
char nnpostfr [FROM_LENGTH];
char newsgroups [NEWSGROUPS_LENGTH];
char followup_to [NEWSGROUPS_LENGTH];
char postline [260];
char sigline [260];
(void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
if (ap) {
if (strlen(ap->subject) >= 3 &&
(!memcmp(ap->subject,"Re:",3) ||
!memcmp(ap->subject,"re:",3) ||
!memcmp(ap->subject,"RE:",3))) strcpy(post_subject,"");
else strcpy(post_subject,"Re: ");
strncat(post_subject, ap->subject, sizeof(post_subject));
}
else strcpy(post_subject,"");
sprintf(post_path,"%s!%s", np->client_hostname, zuser);
(void)NNMivput(np,"NNPOSTSJ ",post_subject,-1);
if (ap) {
sprintf(temp,"%d",ap->number);
(void)NNMivput(np,"NNPOSTHA ",temp, -1);
(void)NNMivput(np,"NNPOSTHG ",gp->name, -1);
}
else {
(void)NNMivput(np,"NNPOSTHA ","", -1);
(void)NNMivput(np,"NNPOSTHG ","" ,-1);
}
/*
* Simple-minded and wrong - newsgroups to post to = current one
*
* (void)NNMivput(np,"NNPOSTNG ",gp ? gp->name : "",-1);
*
* The correct way: if we are following up an article, then
* if the Followup_to header is present, use that, else
* use the Newsgroups: header. If not there, use the newsgroup name.
*
* If fresh post, use the newsgroup name.
*/
if (gp) {
if (ap) { /* this is a followup */
strcpy(newsgroups, "");
strcpy(followup_to,"");
get_more_headers(np,ap,newsgroups,followup_to);
if (EQUAL(followup_to,"poster")) {
ERR1(
"Followups are directed to the poster. Suggest you use REPLY instead."
);
postdefault = "";
}
else if (strchr(followup_to,'@')) {
ERR1(
"Followup header contains mailing address. Suggest you REPLY instead."
);
postdefault = "";
}
else if (*followup_to) postdefault = followup_to;
else if (*newsgroups) postdefault = newsgroups;
else postdefault = gp->name;
}
else { /* this is a fresh posting */
postdefault = gp->name;
}
}
else {
postdefault = "";
}
(void)NNMivput(np,"NNPOSTNG ",postdefault,-1);
/* Can't use this - C/370 compiler bug... */
/* strcpy(tempdsn,ap ? "" : np->maildsn); */
if (ap) strcpy(tempdsn,"");
else strcpy(tempdsn,np->maildsn);
if (!*tempdsn) {
if (!tmpnam(tempdsn)) {
ERR1(
"A temporary data set name could not be created. tmpnam() error."
);
return;
}
if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
ERR2("Error trying to open temp data set: %s", tempdsn);
return;
}
if (fclose(efp) < 0) {
ERR2("Error trying to close temp data set: %s", tempdsn);
return;
}
efp = NULL;
if (!ap) strcpy(np->maildsn,tempdsn);
}
while (NNMdispl(np,"NNMQPOST") == 0) {
NNMivget(np,"NNPOSTNG ",nnpostng, sizeof(nnpostng));
NNMivget(np,"NNPOSTRT ",nnpostrt, sizeof(nnpostrt));
NNMivget(np,"NNPOSTFO ",nnpostfo, sizeof(nnpostfo));
NNMivget(np,"NNPOSTFR ",nnpostfr, sizeof(nnpostfr));
NNMivget(np,"NNPOSTSJ ",post_subject, sizeof(post_subject) );
NNMivget(np,"NNPOSTSF ",signature_file, sizeof(signature_file) );
NNMivget(np,"NNEDPROF ",edit_profile, sizeof(edit_profile) );
/* Create correctly formatted newsgroup listing. */
make_comma_delimited_list(nnpostng,post_newsgroups);
make_comma_delimited_list(nnpostfo,post_followup_to);
(void)NNMivput(np,"NNTEMPDS ",tempdsn,-1);
/* Insure that we can access the signature file, if given. */
if (*signature_file) {
if (!(sfp=fopen(signature_file,"r"))) {
perror(signature_file);
ERR2("Cannot open signature file %s. Check that it is valid.",
signature_file);
continue;
}
}
else sfp = NULL;
/* Fill temporary data set with message to which we are replying,
* if this is a FOLLOWUP request,
* and the contents of the signature file if any.
*/
if (!filled) {
if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
ERR2("Error trying to open temp data set: %s", tempdsn);
continue;
}
if (ap) {
np->extract_file = efp;
np->extract_appending = FALSE;
np->extract_separator_line = FALSE;
np->extract_tab_expanding = TRUE;
np->following_up = TRUE;
fprintf(efp, "In article %s,\n%s writes:\n\n",
ap->message_id, ap->from);
(void)NNMxtx(np,ap,FALSE); /* Extract article text */
np->following_up = FALSE;
if (ferror(efp)) {
ERR2("Error trying to write to temp data set: %s", tempdsn);
continue;
}
}
if (sfp) {
fprintf(efp,"\n--\n",efp);
if (ferror(efp)) np->extract_write_error = TRUE;
for (;;) {
fgets(sigline,sizeof(sigline),sfp);
if (ferror(sfp)) {
ERR2(
"Cannot read from signature file %s. Check that it is valid.",
signature_file);
break;
}
if (feof(sfp)) break;
if ((cp=strchr(sigline,'\n'))) *cp = '\0';
l = strlen(sigline);
fwrite(sigline,(l>251 ? 251 : l),1,efp);
if (ferror(efp)) {
np->extract_write_error = TRUE; break;
}
if (fputc('\n',efp) == EOF) {
np->extract_write_error = TRUE; break;
}
}
(void)fclose(sfp);
if (ferror(efp)) {
ERR2("Error trying to write to temp data set: %s", tempdsn);
continue;
}
}
if (fclose(efp) < 0) {
ERR2("Error trying to close temp data set: %s", tempdsn);
continue;
}
filled = TRUE;
}
efp = NULL;
#ifndef I370
sprintf(editstr,"EDIT DATASET(%s) PROFILE(%s)",tempdsn,edit_profile);
#else
sprintf(editstr, "EDIT DATASET('%s') PROFILE(%s)",
tempdsn+4, edit_profile);
#endif
edit_error = FALSE;
(void)NNMispf(np,editstr);
switch (np->ispfrc) {
case 0: edit_error = FALSE; break;
case 4: ERR1(
"Edit ended without SAVE, posting cancelled. Reenter and SAVE to post."
); continue;
default: edit_error = TRUE; break;
}
if (edit_error) continue;
/* Confirm posting. */
(void)NNMispf (np,"ADDPOP ");
display_rc = NNMdispl(np,"NNMPCONP");
(void)NNMispf (np,"REMPOP ");
(void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
if (display_rc > 0) continue;
if (*zcmd == 'c' || *zcmd == 'C') {
(void)NNMivput(np,"ZCMD ","",-1);
ERR1("Posting cancelled by user. Reenter EDIT and SAVE to post.");
return;
}
if (!(efp = fopen(tempdsn,"r"))) {
ERR2("Error trying to open temp data set: %s", tempdsn);
continue;
}
/* Start posting here.
*
* Me: POST
* Server: 340 send article to be posted. End with <CR-LF>.<CR-LF>
* or: 440 posting not allowed
* If 430...
*
* See RFC850 for details.
*
* Me: required_header: xxx
* ...
* Me: <null line>
* Read text from tempdsn
* Me: <text with leading periods hacked>
* Me: .
* Server: 240 article posted OK
* or: 441 posting failed
*/
/* See RFC 1036 for full information. */
/* Required headers - from, date, subject, newsgroups,
* message-id, path
*/
/* Optional headers - reply-to, sender, followup-to, expires, xref,
* references, control, distribution, lines,
* organization, keywords, summary, approved
*/
/* Get current date and time, and generate a message id from it.
* If the message id is a duplicate, loop around until it isn't.
*/
do {
time(<ime);
now = localtime(<ime);
strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",now);
strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",now);
sprintf(post_message_id,"<%s%s@%s>",
midstr, zuser, np->client_hostname);
} while (EQUAL(post_message_id,np->messageid));
strcpy(np->messageid,post_message_id);
do {
strcpy(np->nntp_command,"POST");
if (!NNMsockt(np)) break; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) break; /* Get server line */
switch (np->nntp_message_num) {
case 340: post_error = FALSE;
break;
case 440: ERR2(
"Posting not allowed. Server %s did not accept the post.",
np->nnserver);
post_error = TRUE;
break;
default: NNMrperr(np); /* Report protocol error */
post_error = TRUE;
break;
}
if (post_error) break;
/* Assert np->server_finished_replying == TRUE
* && np->receiving_text == TRUE
*/
if (*nnpostfr)
sprintf(post_from,"%s@%s (%s)",
zuser, np->client_hostname, nnpostfr);
else sprintf(post_from,"%s@%s",
zuser, np->client_hostname);
sprintf(np->nntp_command,"Path: %s", post_path);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Newsgroups: %s",post_newsgroups);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Subject: %s",post_subject);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Message-ID: %s", post_message_id);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"From: %s", post_from);
if (!NNMsockt(np)) break; /* Send socket command to server */
sprintf(np->nntp_command,"Date: %s", datestr);
if (!NNMsockt(np)) break; /* Send socket command to server */
/* insert optional headers here if we ever have any */
sprintf(np->nntp_command,"Sender: MVS NNTP News Reader <%s@%s>",
NNMVS_NAME, np->client_hostname);
if (!NNMsockt(np)) break; /* Send socket command to server */
if (ap) {
/*
* Uncomment this section when a references field in the
* newsarticle struct is added. Will require total recompilation
*
* if (ap->references)
* sprintf(np->nntp_command,"References: %s %s",
* ap->references, ap->message_id);
* else
*/
sprintf(np->nntp_command,"References: %s",ap->message_id);
if (!NNMsockt(np)) break; /* Send socket command to server */
}
/* optional headers */
if (*nnpostrt) {
sprintf(np->nntp_command,"Reply-to: %s", nnpostrt);
if (!NNMsockt(np)) break; /* Send socket command to server */
}
if (*post_followup_to) {
sprintf(np->nntp_command,"Followup-to: %s", post_followup_to);
if (!NNMsockt(np)) break; /* Send socket command to server */
}
strcpy(np->nntp_command,"");
if (!NNMsockt(np)) break; /* Send socket command to server */
while (!feof(efp) && !ferror(efp)) {
fgets(postline,sizeof(postline),efp);
if (feof(efp)) break;
if (ferror(efp)) break;
if (*postline && postline[l=strlen(postline)-1] == '\n')
postline[l] = '\0';
if (postline[0] == '.') strcpy(np->nntp_command,".");
else strcpy(np->nntp_command,"");
strcat(np->nntp_command,postline);
if (!NNMsockt(np)) break; /* Send socket command to server */
}
strcpy(np->nntp_command,".");
if (!NNMsockt(np)) break; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) break; /* Get server line */
switch (np->nntp_message_num) {
case 240: post_error = FALSE;
break;
case 441: NNMclrtx(np,NULL); /* Clear text */
NNMouttx(np,np->server_buf,NULL);/* Output text line */
NNMvtx(np,NULL,NULL); /* View text */
ERR2("Posting failed. Server %s rejected the post.",np->nnserver);
post_error = TRUE;
break;
default: NNMrperr(np); /* Report protocol error */
post_error = TRUE;
break;
}
NNMesrvr(np); /* End server read */
break;
} while(FALSE); /* one-time DO so I can break out of it */
if (!post_error) {
(void)NNMivput(np,"NNPOSTID ",post_message_id,-1);
WARN2("Your article has been posted. Message ID: %s",
post_message_id);
break;
}
}
if (!efp) return;
if (ferror(efp)) {
ERR2("Error trying to read from temp data set: %s", tempdsn);
}
if (fclose(efp) < 0) {
ERR2("Error trying to close temp data set: %s", tempdsn);
}
if (ap) {
if (remove(tempdsn) < 0) {
ERR2("Error trying to delete temp data set: %s", tempdsn);
}
}
return;
}
./ ADD NAME=NNMDSOPT,SSI=01010013
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DSOPT")
#pragma csect(static,"NN$DSOPT")
#include "nn.h"
/****** Set options. *************************************************/
static void
set_options(np,panelname,which)
Rstruc nncb *np;
char *panelname;
enum user_option which;
{
while (NNMdispl(np,panelname) == 0) {
NNMsopt(np,which); /* Actually set options */
}
return;
}
/****** Option ... set NNMVS default processing options. *************/
void
NNMdsopt(np,option)
Rstruc nncb *np;
char *option;
{
Bool asked_for;
Bool force_choice;
char nnchoice[9];
force_choice = FALSE;
do {
asked_for = TRUE;
if (!force_choice && option && *option) {
strncpy(nnchoice,option,sizeof(nnchoice)-1);
}
else {
(void)NNMispf(np,"ADDPOP");
if (NNMdispl(np,"NNMPOPT ") > 0) {
asked_for = FALSE;
}
else {
(void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
if (*nnchoice == '?') {
ERR1("Invalid choice;\
Move the cursor to a selection (or type S next to it) and press ENTER."
);
}
}
(void)NNMispf(np,"REMPOP");
}
if (asked_for) {
if (EQUAL(nnchoice,"1")) {
set_options(np,"NNMRFCH ",OPTION_HEADER);
break;
}
else if (EQUAL(nnchoice,"2")) {
set_options(np,"NNMOPTS ",OPTION_OTHER);
break;
}
else if (EQUAL(nnchoice,"3")) {
set_options(np,"NNMOPTT ",OPTION_VIEW);
break;
}
else {
ERR1("Invalid choice;\
Move the cursor to a selection (or type S next to it) and press ENTER."
);
force_choice = TRUE;
continue;
}
}
} while (asked_for);
return;
}
./ ADD NAME=NNMDUMP,SSI=01010055
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@DUMP ")
#pragma csect(static,"NN$DUMP ")
#include "nn.h"
/****** Dump some data. **********************************************/
void
NNMdump(struct nncb *np, char *label, char *p,int r)
{
int i;
if (!np->debug_file) return;
if (r == -2) {
fprintf(np->debug_file,"%s: %d\n",label,(int)p);
return;
}
if (r == -1) r = strlen(p);
fprintf(np->debug_file,"%s: (%d characters)\n",label,r);
for (i=0;i<77;i++) fprintf(np->debug_file,"-");
fprintf(np->debug_file,"\n");
for (i=0;i<r;i++) {
char c = *(p+i);
if (isprint(c)) fprintf(np->debug_file,"%c",c);
else fprintf(np->debug_file,"<0x%2.2x>",c);
}
fprintf(np->debug_file,"\n");
for (i=0;i<77;i++) fprintf(np->debug_file,"-");
fprintf(np->debug_file,"\n");
fflush(np->debug_file);
return;
}
./ ADD NAME=NNMESRVR,SSI=01020033
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ESRVR")
#pragma csect(static,"NN$ESRVR")
#include "nn.h"
/****** End server read. *********************************************/
void
NNMesrvr(np)
Rstruc nncb *np;
{
char *lp;
Bool found_more_server_data = FALSE;
Bool save_dont_reissue_socket_command;
NNMclrtx(np,NULL); /* Clear text */
save_dont_reissue_socket_command = np->dont_reissue_socket_command;
np->dont_reissue_socket_command = TRUE;
do {
if (NNMgsrvl(np,&lp)) { /* Get server line */
if (lp) {
found_more_server_data = TRUE;
(void)NNMouttx(np,lp,NULL); /* Output text line */
}
}
} while (lp);
if (found_more_server_data) {
ERR1(
"More data was returned by the news server than the client expected."
);
NNMvtx(np,NULL,NULL); /* View text */
}
np->dont_reissue_socket_command = save_dont_reissue_socket_command;
return;
}
./ ADD NAME=NNMESTNG,SSI=01000022
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ESTNG")
#pragma csect(static,"NN$ESTNG")
#include "nn.h"
/****** Establish newsgroup. *****************************************/
Bool
NNMestng(np,group)
Rstruc nncb *np;
char *group;
{
char *lp;
Bool null_group_passed = FALSE;
/* A null group means reissue the server command to select the
current newsgroup if it is necessary. */
if (!group) {
null_group_passed = TRUE;
if (!np->current_newsgroup) {
fprintf(stderr,"NNMestng: no current newsgroup\n");
return FALSE;
}
if (np->newsgroup_selected) return TRUE;
group = np->current_newsgroup->name;
}
np->newsgroup_not_found = FALSE;
/* Send "GROUP xxxx" to news server. */
strcpy(np->nntp_command,"GROUP ");
strcat(np->nntp_command,group);
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
/* Receive response. Should be one of:
* 211 n f l s group selected
* 411 no such news group
*/
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
switch (np->nntp_message_num) {
case 211: /* n f l s group selected */
break;
case 411: /* no such news group */
fprintf(stderr,"%s: no such newsgroup\n",group);
ERR3("No such newsgroup. %s is unknown to server %s.",
group, np->nnserver);
np->newsgroup_not_found = TRUE;
return FALSE;
default:
NNMrperr(np); /* Report protocol error */
return FALSE;
}
np->newsgroup_selected = TRUE;
return TRUE;
}
./ ADD NAME=NNMFREEM,SSI=01010050
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@FREEM")
#pragma csect(static,"NN$FREEM")
#include "nn.h"
/****** Free memory. *************************************************/
void
NNMfreem(np,stuff,whatfor)
Rstruc nncb *np;
char *stuff;
char *whatfor;
{
free(stuff);
if (np->debug_file) {
fprintf(np->debug_file,"NNMfreem: freed memory for %s\n", whatfor);
}
return;
}
./ ADD NAME=NNMGETDS,SSI=011A0058
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@GETDS")
#pragma csect(static,"NN$GETDS")
#include "nn.h"
#define DUMMY_FILE_POINTER_FOR_PDS (FILE *)(-1)
struct sysout {
int copies;
char class [2];
char dest [9];
char forms [5];
char ucs [5];
};
/****** Function to close sequential data set after extraction. ******/
static void
close_seq(np,ep,xfp,final)
Rstruc nncb *np;
Rstruc extraction *ep;
FILE *xfp;
Fool final;
{
if (fclose(xfp) < 0) {
/* perror(ep->dsname); */
ERR2("An error occurred closing %s.", ep->dsname);
np->extract_close_error = TRUE;
}
}
/****** Function to close partitioned data set after extraction. *****/
static void
close_pds(np,ep,xfp,final)
Rstruc nncb *np;
Rstruc extraction *ep;
FILE *xfp;
Fool final;
{
if (final) {
(void)NNMunalc(ep->ddname); /* Unallocate the PDS */
}
else {
if (fclose(xfp) < 0) {
/* perror(ep->dsname); */
ERR2("An error occurred closing %s.", ep->dsname);
np->extract_close_error = TRUE;
}
}
}
/****** Function to close SYSOUT print file after printing. **********/
static void
close_jes(np,ep,xfp,final)
Rstruc nncb *np;
Rstruc extraction *ep;
FILE *xfp;
Fool final;
{
if (fclose(xfp) < 0) {
/* perror(ep->dsname); */
ERR2("An error occurred closing %s.", ep->dsname);
np->extract_close_error = TRUE;
}
if (final) {
(void)NNMunalc(ep->ddname); /* Unallocate the SYSOUT file */
}
}
/****** Allocate SYSOUT file. ****************************************/
static Bool
allocate_sysout(ep,sp)
Rstruc extraction *ep;
Rstruc sysout *sp;
{
int i;
int rc;
char *cp;
__S99parms stuff99; /* The manual has it wrong. No "struct". */
TEXTUNIT *tu [ 7];
TEXTUNIT tu_sysout;
TEXTUNIT tu_copies;
TEXTUNIT tu_dest;
TEXTUNIT tu_forms;
TEXTUNIT tu_ucs;
TEXTUNIT tu_rtddn;
memset((char *)&stuff99,0,sizeof(__S99parms));
stuff99.__S99RBLN = 20;
stuff99.__S99VERB = S99VRBAL;
stuff99.__S99FLAG1 = S99NOCNV << 8;
stuff99.__S99ERROR = 0;
stuff99.__S99INFO = 0;
stuff99.__S99TXTPP = tu;
stuff99.__S99FLAG2 = 0;
i = 0;
tu[i++] = &tu_sysout;
tu_sysout.key = DALSYSOU;
tu_sysout.num = 1;
tu_sysout.ent.len = 1;
tu_sysout.ent.prm[0] = toupper(sp->class[0]);
tu[i++] = &tu_copies;
tu_copies.key = DALCOPYS;
tu_copies.num = 1;
tu_copies.ent.len = 1;
tu_copies.ent.prm[0] = (unsigned char)sp->copies;
if (sp->dest[0] > ' ') {
tu[i++] = &tu_dest;
tu_dest.key = DALSUSER;
tu_dest.num = 1;
copy_uppercase_and_strip_trailing(tu_dest.ent.prm,sp->dest,cp);
tu_dest.ent.len = cp - tu_dest.ent.prm;
}
if (sp->forms[0] > ' ') {
tu[i++] = &tu_forms;
tu_forms.key = DALSFMNO;
tu_forms.num = 1;
copy_uppercase_and_strip_trailing(tu_forms.ent.prm,sp->forms,cp);
tu_forms.ent.len = cp - tu_forms.ent.prm;
}
if (sp->ucs[0] > ' ') {
tu[i++] = &tu_ucs;
tu_ucs.key = DALUCS;
tu_ucs.num = 1;
copy_uppercase_and_strip_trailing(tu_ucs.ent.prm,sp->ucs,cp);
tu_ucs.ent.len = cp - tu_ucs.ent.prm;
}
tu[i++] = &tu_rtddn;
tu_rtddn.key = DALRTDDN;
tu_rtddn.num = 1;
tu_rtddn.ent.len = 8;
memset(tu_rtddn.ent.prm,' ',8);
tu[i] = (void *)0x80000000;
rc = svc99(&stuff99);
if (rc == 0) {
memcpy(ep->ddname,(char *)tu_rtddn.ent.prm,8);
ep->ddname[8] = ' ';
*(strchr(ep->ddname,' ')) = '\0';
return TRUE;
}
else {
NNMdfail(rc,&stuff99);
return FALSE;
}
}
/****** Prompt user for the name of a data set to extract into. ******/
FILE *
NNMgetds(np,ep)
Rstruc nncb *np;
Rstruc extraction *ep;
{
FILE *xfp;
char *panel_to_display;
Bool asked_for;
struct sysout sys;
char nnexdsn[65]; /* data set name for extraction */
char nnexapp [4]; /* YES or NO for append mode */
char nnextab [4]; /* YES or NO for tab expansion */
char nnexblk [4]; /* YES or NO for blank after sep*/
char nnexspa [4]; /* YES or NO for page ejects */
char nnexsep[81]; /* Separator line (optional) */
char nnexan1[16]; /* From article number */
char nnexan2[16]; /* To article number */
char nnexpmp [9]; /* PDS member name prefix */
char nnexscl [2]; /* Print SYSOUT class name */
char nnexsco [4]; /* Print SYSOUT copies number */
char nnexsde [9]; /* Print SYSOUT destination */
char nnexsfo [5]; /* Print SYSOUT forms */
char nnexsuc [5]; /* Print SYSOUT UCS */
char quoted_dsname [67];
/* Display panel asking for data set name into which to extract. */
xfp = NULL;
asked_for = TRUE;
(void)NNMispf(np,"ADDPOP");
if (ep->mode == JES) {
(void)NNMivput(np,"NNWHICH ",ep->panelname,-1);
(void)NNMivput(np,"NNALLPR ",
#ifdef FULLSYSOUT
"Y",
#else
"",
#endif
-1);
panel_to_display = "NNMPPRT ";
}
else panel_to_display = ep->panelname;
while (!xfp) {
/* Keep asking for a dsname until one works or END pressed. */
if (NNMdispl(np,panel_to_display) > 0) {
asked_for = FALSE;
xfp = NULL;
break;
}
if (ep->mode == JES) {
(void)NNMivget(np,"NNEXSCL ",nnexscl,sizeof(nnexscl));
(void)NNMivget(np,"NNEXSCO ",nnexsco,sizeof(nnexsco));
#ifdef FULLSYSOUT
(void)NNMivget(np,"NNEXSDE ",nnexsde,sizeof(nnexsde));
(void)NNMivget(np,"NNEXSFO ",nnexsfo,sizeof(nnexsfo));
(void)NNMivget(np,"NNEXSUC ",nnexsuc,sizeof(nnexsuc));
#else
*nnexsde = '\0';
*nnexsfo = '\0';
*nnexsuc = '\0';
#endif
(void)NNMivget(np,"NNEXAN1 ",nnexan1,sizeof(nnexan1));
(void)NNMivget(np,"NNEXAN2 ",nnexan2,sizeof(nnexan2));
(void)NNMivget(np,"NNEXSPA ",nnexspa,sizeof(nnexspa));
(void)NNMivget(np,"NNEXBLK ",nnexblk,sizeof(nnexblk));
(void)NNMivget(np,"NNEXSEP ",nnexsep,sizeof(nnexsep));
}
else {
(void)NNMivget(np,"NNEXDSN ",nnexdsn,sizeof(nnexdsn));
(void)NNMivget(np,"NNEXTAB ",nnextab,sizeof(nnextab));
(void)NNMivget(np,"NNEXAN1 ",nnexan1,sizeof(nnexan1));
(void)NNMivget(np,"NNEXAN2 ",nnexan2,sizeof(nnexan2));
if (ep->mode == PDS) {
(void)NNMivget(np,"NNEXPMP ",nnexpmp,sizeof(nnexpmp));
}
else {
(void)NNMivget(np,"NNEXAPP ",nnexapp,sizeof(nnexapp));
(void)NNMivget(np,"NNEXBLK ",nnexblk,sizeof(nnexblk));
(void)NNMivget(np,"NNEXSEP ",nnexsep,sizeof(nnexsep));
}
}
if (ep->mode == PDS) {
ep->closer = close_pds;
ep->appending = FALSE;
ep->blanking = FALSE;
strcpy(ep->separator,"");
strcpy(ep->ddname,"");
strcpy(ep->member_prefix,nnexpmp);
/* Note: panel forces fully-qualified name to pass to allocate */
if (nnexdsn[0] != '\'') {
strcpy(quoted_dsname,"'");
strcat(quoted_dsname,nnexdsn);
strcat(quoted_dsname,"'");
}
else strcpy(quoted_dsname,nnexdsn);
/* Check if PDS already exists. */
if (np->warn_overwrite) {
if (TEST_IF_FILE_EXISTS(xfp,quoted_dsname)) {
CLEANUP_IF_FILE_EXISTS(xfp);
xfp = NULL;
if (NNMdispl(np,"NNMPEXPW") > 0) {
WARN1("Operation cancelled, because you pressed END.");
break;
}
}
}
if (!NNMalloc(nnexdsn,ep->ddname,PDS,ep->article_count)) {
ERR2("Allocation failed for data set %s.", nnexdsn);
xfp = NULL;
continue;
}
strcpy(ep->dsname, nnexdsn);
ep->tab_expanding = (nnextab[0] == 'Y');
}
else if (ep->mode == JES) {
ep->closer = close_jes;
strcpy(ep->separator, nnexsep);
sprintf(ep->dsname,"SYSOUT class %s",nnexscl);
memset(&sys,0,sizeof(sys));
strcpy(sys.class, nnexscl);
sys.copies = atoi(nnexsco);
if (sys.copies < 1) sys.copies = 1;
strcpy(sys.dest, nnexsde);
strcpy(sys.forms, nnexsfo);
strcpy(sys.ucs, nnexsuc);
ep->ejecting = (nnexspa[0] == 'Y');
ep->appending = FALSE;
ep->blanking = (nnexblk[0] == 'Y');
ep->tab_expanding = TRUE;
}
else {
ep->closer = close_seq;
strcpy(ep->separator, nnexsep);
strcpy(ep->dsname, nnexdsn);
ep->appending = (nnexapp[0] == 'Y');
ep->blanking = (nnexblk[0] == 'Y');
ep->tab_expanding = (nnextab[0] == 'Y');
}
if (*nnexan1) ep->from_article_number = atoi(nnexan1);
else ep->from_article_number = 0;
if (*nnexan2) ep->to_article_number = atoi(nnexan2);
else ep->to_article_number = INT_MAX;
/* check if the dataset already exists */
/* (Wonder if this will compile. Have fun, "cc"...) */
if (ep->mode != JES) {
if (ep->appending ? np->warn_append : np->warn_overwrite) {
if (TEST_IF_FILE_EXISTS(xfp,nnexdsn)) {
CLEANUP_IF_FILE_EXISTS(xfp);
xfp = NULL;
if (NNMdispl(np,"NNMPEXOW") > 0) {
WARN1("Operation cancelled, because you pressed END.");
break;
}
}
}
}
if (ep->mode == JES) {
if (allocate_sysout(ep,&sys)) {
sprintf(nnexdsn,"dd:%s",ep->ddname);
}
else *nnexdsn = '\0';
}
if (ep->mode == PDS) {
xfp = DUMMY_FILE_POINTER_FOR_PDS;
break;
}
if (*nnexdsn) {
if (ep->mode == JES) {
xfp = OPEN_SYSOUT_FILE(nnexdsn);
}
else {
xfp = OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(nnexdsn,ep->appending);
}
if (!xfp) {
fprintf(stderr,"Open failure: errno=%d\n",errno);
perror(nnexdsn);
ERR2("Cannot open %s.", ep->dsname);
}
}
}
(void)NNMispf(np,"REMPOP");
return xfp;
}
./ ADD NAME=NNMGETM,SSI=01000041
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@GETM ")
#pragma csect(static,"NN$GETM ")
#include "nn.h"
/****** Get memory. **************************************************/
void
NNMgetm(np,pointer,howmuch,whatfor)
Rstruc nncb *np;
char **pointer;
int howmuch;
char *whatfor;
{
*pointer = (char *)malloc(howmuch);
if (!*pointer) {
fprintf(stderr,"NNMVS: Cannot obtain %d bytes of memory for %s\n",
howmuch,whatfor);
}
else if (np->debug_file) {
fprintf(np->debug_file,"NNMgetm: got %d bytes of memory for %s\n",
howmuch,whatfor);
}
return;
}
./ ADD NAME=NNMGSRVL,SSI=011D0050
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@GSRVL")
#pragma csect(static,"NN$GSRVL")
#include "nn.h"
#define GOT_NOTHING 0
#define GOT_SOMETHING 1
#define GOT_DISCONNECT 2
#define GOT_NOTAUTHORIZED 3
/* separate this and call it NNMGAUTH eventually */
/****** Send authorization to news server. ***************************/
static Bool
NNMgauth(np)
Rstruc nncb *np;
{
char *lp;
FILE *fp;
int display_rc;
Bool auth_error;
Bool connection_probably_closed;
char nnauser [65];
char nnapass [65];
/* NNTP numbers must be the following as defined in C News source:
*
* OK_AUTHSYS 280 authorization system OK
* OK_AUTH 281 authorization OK
* NEED_AUTHINFO 380 authorization is required
* NEED_AUTHDATA 381 <type> authorization data required (e.g. PASS)
* ERR_NOAUTH 480 authorization required for command
* ERR_AUTHSYS 481 authorization system invalid
* ERR_AUTHREJ 482 authorization data rejected
* ERR_CMDSYN 501 command syntax error
* ERR_COMMAND 500 command not implemented
* ERR_ACCESS 502 access to server denied
* ERR_AUTHBAD 580 authorization failed
*
* Me: AUTHINFO USER username
* Server: 381 PASS required
* or: 482 Authorization already completed
* or: 500 Command not recognized
*
* If 482, server does not accept our attempt to gain authorization.
*
* If 500, authorization is not needed or the server has never
* heard of authorization. Either way, we proceed as "authorized".
*
* If 381 ...
*
* Me: AUTHINFO PASS password
* Server: 281 Authorization OK
* or: 482 authorization data rejected
* or: 502 access to server denied
* or: 580 authorization failed
*
* If 502, the server has disconnected me and I should return FALSE.
* Otherwise, everything is OK, and I should return TRUE.
*
*/
lp = "None - local system error accessing authorization file";
auth_error = FALSE;
connection_probably_closed = FALSE;
*nnauser = '\0';
*nnapass = '\0';
(void)NNMivget(np,"NNAUSER ",nnauser,sizeof(nnauser));
if (!*nnauser) {
(void)NNMivget(np,"ZUSER ",nnauser,sizeof(nnauser));
lowercase_in_place(nnauser);
(void)NNMivput(np,"NNAUSER ",nnauser,-1);
}
/* Read user and pass from terminal */
/* temporary. change to panel */
(void)NNMivput(np,"NNSERVER ",np->nnserver,-1);
(void)NNMispf(np,"ADDPOP");
(void)NNMdispl(np,"NNMPGAUT");
display_rc = np->ispfrc;
(void)NNMispf(np,"REMPOP");
if (display_rc != 0) return FALSE;
(void)NNMivget(np,"NNAUSER ",nnauser,sizeof(nnauser));
(void)NNMivget(np,"NNAPASS ",nnapass,sizeof(nnapass));
sprintf(np->nntp_command,"AUTHINFO USER %s", nnauser);
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
switch (np->nntp_message_num) {
case 381: /* PASS required */
break;
default: NNMrperr(np); /* Report protocol error */
auth_error = TRUE;
break;
}
if (!auth_error) {
sprintf(np->nntp_command,"AUTHINFO PASS %s", nnapass);
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
switch (np->nntp_message_num) {
case 281: /* authorization OK */
return TRUE;
case 502: /* access to server denied */
/* Also, we have been disconnected at this point. */
connection_probably_closed = TRUE;
auth_error = TRUE;
break;
default: NNMrperr(np); /* Report protocol error */
auth_error = TRUE;
break;
}
}
NNMesrvr(np); /* End server read */
if (auth_error) {
if (connection_probably_closed) {
ERR2("Authorization failed;\
The NNTP server at %s refuses to authorize you. \
Some news operations may fail.",\
np->nnserver);
/* np->connection_broken = TRUE; */
/* NNMdisc(np); */ /* Complete disconnection */
return FALSE;
}
else {
if (np->batch_mode) {
fprintf(stderr,
"NNMVS could not obtain authorization from the NNTP server.\n");
fprintf(stderr,
"NNMVS will proceed, but some news operations may fail.\n");
fprintf(stderr,
"The response from server %s was:\n\n%s\n\n", np->nnserver,lp);
return FALSE;
}
else {
NNMivput(np,"NNSRVRSP ",lp, -1);
(void)NNMispf(np,"ADDPOP ");
(void)NNMispf(np,"DISPLAY PANEL(NNMPAUTH)");
display_rc = np->ispfrc;
(void)NNMispf(np,"REMPOP ");
if (display_rc == 0) return FALSE;
else {
/* NNMdisc(np); */
return FALSE;
}
}
}
}
return TRUE;
}
/****** Input one character from the server. *************************/
static int
socket_getchar(np)
Rstruc nncb *np;
{
int readrc;
if (np->g_buf_index == -1 ||
np->g_buf_index >= np->g_bytes_returned - 1) {
np->g_buf_index = -1;
if (np->dont_read) return(SOCKET_NO_MORE);
else {
TCP_DEBUG_ON;
readrc = read(np->socknum, np->g_buf, READ_BYTES);
TCP_DEBUG_OFF;
if (readrc == -1) {
np->connection_broken = TRUE;
return SOCKET_GETCHAR_ERROR;
}
else if (readrc == 0) {
np->connection_broken = TRUE;
return SOCKET_READ_NOTHING;
}
else {
#ifdef MVS
ASCII_TO_EBCDIC(np->g_buf,readrc);
#endif
np->g_bytes_returned = readrc;
if (np->debug_file) {
NNMdump(np,"Data read from server",np->g_buf,readrc);
}
}
}
}
return np->g_buf[++np->g_buf_index];
}
/****** Input one data line at a time from the server. ***************/
static enum socket_retval
socket_from_server(np)
Rstruc nncb *np;
{
char *s_buf;
int s_bytes;
int s_buf_index;
int character;
int previous_character;
s_buf = np->server_buf;
s_bytes = SERVER_BUF_MSGSIZE;
/* Get characters from the server until CRLF is reached. */
s_buf_index = 0;
previous_character = -1;
for (;;) {
character = socket_getchar(np);
if (character == LINE_FEED && previous_character == CARRIAGE_RETURN)
break;
if (character == SOCKET_GETCHAR_ERROR) return(SERVER_READ_ERROR);
if (character == SOCKET_NO_MORE) return(SERVER_NO_MORE);
if (character == SOCKET_READ_NOTHING) return(SERVER_READ_ERROR);
previous_character = character;
if (s_buf_index >= s_bytes) {
fprintf(stderr,"Error: np->server_buf overflowed.\n");
fprintf(stderr,
"More than %d bytes collected without CR/LF seen.\n",
s_bytes);
if (np->debug_file) {
NNMdump(np,"Data collected so far",np->server_buf,s_bytes);
}
return(SERVER_BUFFER_ERROR);
}
if (character == '\0') {
fprintf(stderr,
"Warning: null character found in data from server, changed to blank\n"
);
character = ' ';
}
s_buf[s_buf_index++] = (unsigned char)character;
}
s_buf[s_buf_index] = '\0';
return(SERVER_READ_OK);
}
/****** Try to reconnect. ********************************************/
static Bool
try_to_reconnect(np)
Rstruc nncb *np;
{
if (np->closing_connection || np->reconnect_in_progress) return FALSE;
if (!NNMrecon(np)) return FALSE; /* Reconnect to server */
/* have to reissue most recently written command */
if (np->dont_reissue_socket_command) {
NNMesrvr(np); /* End server read */
}
else if (!NNMsockt(np)) { /* Send socket command to server */
return FALSE;
}
WARN2("Successfully reconnected to server %s after disconnect.",
np->nnserver);
return TRUE;
}
/****** Try to authorize. ********************************************/
static Bool
try_to_authorize(np)
Rstruc nncb *np;
{
char save_command[CLIENT_BUF_MSGSIZE+4];
Bool rc;
if (np->closing_connection) return FALSE;
NNMesrvr(np); /* End server read */
strcpy(save_command,np->nntp_command);
rc = NNMgauth(np); /* Get authorization */
strcpy(np->nntp_command,save_command);
if (!rc) return FALSE;
/* have to reissue most recently written command */
if (np->dont_reissue_socket_command) {
NNMesrvr(np); /* End server read */
}
else if (!NNMsockt(np)) { /* Send socket command to server */
return FALSE;
}
return TRUE;
}
/****** Try to get something. ****************************************/
static int
try_to_get_something(np,pointer)
Rstruc nncb *np;
char **pointer;
{
char *sbufp;
char *p;
int scan_count;
Bool authorization_required; /* put this in nncb? */
authorization_required = FALSE;
switch (socket_from_server(np)) {
case SERVER_READ_OK: break;
case SERVER_READ_ERROR: ERR2(
"Lost server connection. Failure reading data from server %s.",
np->nnserver);
np->time_to_go_home = TRUE;
break;
case SERVER_BUFFER_ERROR: ERR2(
"Read error. No linefeed character found in data from server %s.",
np->nnserver);
np->time_to_go_home = TRUE;
break;
case SERVER_NO_MORE: np->server_has_something_pending = FALSE;
break;
}
if (np->connection_broken) return GOT_DISCONNECT;
if (np->time_to_go_home) return GOT_NOTHING;
if (np->dont_read && !np->server_has_something_pending)
return GOT_SOMETHING;
np->something_to_print = TRUE;
sbufp = np->server_buf;
if (np->sending_text) {
if (*sbufp == '.') {
/*
NNMdump(np,"Line that starts with a period",sbufp,strlen(sbufp));
*/
switch (*(sbufp+1)) {
case CARRIAGE_RETURN:
case LINE_FEED:
case '\0':
np->server_finished_replying = TRUE;
/* np->something_to_print = FALSE; */
break;
case '.':
break;
default:
NNMdump(np,"Warning, bad period in line from server",
sbufp,strlen(sbufp));
break;
}
}
else /* nothing - still sending that there text */ ;
np->nntp_message_num = NO_NNTP_MESSAGE_NUM;
np->nntp_message_text = sbufp;
}
else {
np->nntp_message_num = NO_NNTP_MESSAGE_NUM;
scan_count = 0;
sscanf(sbufp,"%d %n",&np->nntp_message_num,&scan_count);
np->nntp_message_text = sbufp + scan_count;
/* NNMdump(np,"message_num", np->nntp_message_num, -2); */
/* NNMdump(np,"message_text",np->nntp_message_text,-1); */
switch (np->nntp_message_num) {
case 205:
case 400:
/* case 502: */
np->server_finished_replying = TRUE;
np->time_to_go_home = TRUE;
break;
case 503:
np->server_finished_replying = TRUE;
np->connection_broken = TRUE;
np->time_to_go_home = TRUE;
np->g_bytes_returned = 0;
np->g_buf_index = -1;
np->something_to_print = FALSE;
break;
case 380:
case 480:
authorization_required = TRUE;
np->server_finished_replying = TRUE;
np->connection_broken = FALSE;
np->g_bytes_returned = 0;
np->g_buf_index = -1;
np->something_to_print = FALSE;
break;
case 335:
case 340:
np->server_finished_replying = TRUE;
np->receiving_text = TRUE;
break;
case 100:
case 199:
case 215:
case 220:
case 221:
case 222:
case 230:
case 231:
np->sending_text = TRUE;
break;
case NO_NNTP_MESSAGE_NUM:
fprintf(stderr,
"Error: No NNTP message ID number in response from server %s.\n",
np->nnserver);
np->sending_text = TRUE;
np->receiving_text = FALSE;
break;
default:
np->server_finished_replying = TRUE;
break;
}
}
if (np->something_to_print) {
/* Last character of output buffer is a CR without LF. */
p = sbufp + strlen(sbufp)-1;
if (p >= sbufp) {
if (*p == CARRIAGE_RETURN) *p = '\0';
else {
fprintf(stderr,
"Warning: No carriage return in data from server (%d bytes):\n%s\n",
strlen(sbufp), sbufp);
CRIT2(
"Carriage return expected but not seen in data from server %s.",
np->nnserver);
}
}
*pointer = sbufp;
}
if (np->debug_file) {
NNMdump(np,"Response from server",sbufp,strlen(sbufp));
}
return (
np->connection_broken ? GOT_DISCONNECT
: authorization_required ? GOT_NOTAUTHORIZED
: np->time_to_go_home ? GOT_NOTHING
: GOT_SOMETHING
);
}
/****** Get server line. *********************************************/
Bool
NNMgsrvl(np,pointer)
Rstruc nncb *np;
char **pointer;
{
int tries;
Bool retry;
Bool rc;
*pointer = NULL;
if (np->receiving_text) { /* as when POSTing a news item... */
return TRUE;
}
if (np->server_finished_replying) np->dont_read = TRUE;
for (tries=0;tries<2;tries++) {
switch (try_to_get_something(np,pointer)) {
case GOT_SOMETHING: return TRUE;
case GOT_NOTHING: return FALSE;
case GOT_DISCONNECT: if (try_to_reconnect(np)) continue;
else return FALSE;
case GOT_NOTAUTHORIZED: if (try_to_authorize(np)) continue;
else return FALSE;
}
}
}
./ ADD NAME=NNMIERR,SSI=01010042
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@IERR ")
#pragma csect(static,"NN$IERR ")
#include "nn.h"
/****** ISPF error handler. ******************************************/
void
NNMierr(np)
Rstruc nncb *np;
{
char errbuf[] = "DISPLAY PANEL(ISPTERM)";
int errlen;
if (np->batch_mode) {
fprintf(stderr,"ISPF services cannot be called from batch mode.\n");
return;
}
errlen = strlen(errbuf);
switch (ISPEXEC(&errlen,errbuf)) {
case 0:
case 4:
case 8: break;
default: fprintf(stderr,
"\n*** Severe ISPF error, cannot even display ISPTERM error panel.\n");
fprintf(stderr,
"\n*** Return code from ISPF service is %d\n",np->ispfrc);
break;
}
return;
}
./ ADD NAME=NNMIGET,SSI=01000014
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@IGET ")
#pragma csect(static,"NN$IGET ")
#include "nn.h"
/****** Retrieve the value of an ISPF variable into an integer. ******/
int
NNMiget(np,varname)
Rstruc nncb *np;
char *varname;
{
char varbuf[16];
int vcopy_length;
if (!strchr(varname,' ')) {
fprintf(stderr,"NNMiget: no blank passed in var name\n");
return FALSE;
}
vcopy_length = sizeof(varbuf);
np->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
switch (np->ispfrc) {
case 0:
varbuf[vcopy_length] = '\0';
return atoi(varbuf);
case 8:
return 0;
case 16:
fprintf(stderr,
"Error: ISPF variable buffer too short to get %s\n",
varname);
return 0;
default:
NNMierr(np); /* handle ISPF error */
return 0;
}
}
./ ADD NAME=NNMINIT,SSI=01480044
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@INIT ")
#pragma csect(static,"NN$INIT ")
#include "nn.h"
#define ARGSIZE 72
#define clear_subject(X) *(X)->selsubj = '\0'
#define subjectlt(X) subjectcmp(X) < 0
#define NO_COMPARISON TRUE
#define subjectmatch NNMsumat(_subj,_ap->subject)
#define SEMI ;
#define NOTHINGFUN(A) /* */
#define ANYFUN(A) SetUnknown(A)
#define NOFUN(A) /* */
#define SETSUBJECTFUN(A) _subj = set_subject(np,A->subject)
#define SEARCH_FIRST_TO_LAST(Apnew,Apold,Initfun,Compfun,Any) \
SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
(_wp = _wpfirst SEMI _wp <= _wplast SEMI _wp++),\
(_vp = _vpfirst SEMI _vp <= _vplast SEMI _vp++))
#define SEARCH_LAST_TO_FIRST(Apnew,Apold,Initfun,Compfun,Any) \
SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
(_wp = _wplast SEMI _wp >= _wpfirst SEMI _wp--),\
(_vp = _vplast SEMI _vp >= _vpfirst SEMI _vp--))
#define SEARCH_CURRENT_TO_FIRST(Apnew,Apold,Initfun,Compfun,Any) \
SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
(_wp = (np->current_sortvark-1) SEMI _wp >= _wpfirst SEMI _wp--),\
(_vp = &GETVARK(gp,Apold->number)-1 SEMI _vp >= _vpfirst SEMI _vp--))
#define SEARCH_CURRENT_TO_LAST(Apnew,Apold,Initfun,Compfun,Any) \
SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
(_wp = (np->current_sortvark+1) SEMI _wp <= _wplast SEMI _wp++),\
(_vp = &GETVARK(gp,Apold->number)+1 SEMI _vp <= _vplast SEMI _vp++))
#define SEARCH(Apnew,Apold,Initexp,Compexp,Anyexp,Forwp,Forvp) \
{\
struct newsarticle *_ap;\
VARK *_vp;\
VARK *_vpfirst;\
VARK *_vplast;\
VARK **_wp;\
VARK **_wpfirst;\
VARK **_wplast;\
char *_subj;\
\
Initexp(Apold);\
Apnew = NULL;\
if (gp->sort_vector) {\
_wpfirst = gp->sort_vector;\
_wplast = gp->sort_vector + gp->sort_count - 1;\
for Forwp {\
vp = *_wp;\
Anyexp(*vp);\
if (NNMcar(np,gp,0,vp,&_ap,&cd,RETRIEVE) && (Compexp)) {\
np->current_sortvark = _wp;\
Apnew = _ap;\
break;\
}\
}\
}\
else if (gp->article_vector) {\
_vpfirst = &GETVARKFIRST(gp);\
_vplast = &GETVARKLAST(gp);\
for Forvp {\
vp = _vp;\
Anyexp(*vp);\
if (NNMcar(np,gp,0,vp,&_ap,&cd,RETRIEVE) && (Compexp)) {\
Apnew = _ap;\
break;\
}\
}\
}\
}
#define ERROR_NEXT_ARTICLE \
"There are no further articles in this newsgroup."
#define ERROR_PREV_ARTICLE \
"There are no previous articles in this newsgroup."
#define ERROR_NEXT_TABLED_ARTICLE \
"There are no more news articles that satisfy the current criteria."
#define ERROR_PREV_TABLED_ARTICLE \
"There are no previous news articles that satisfy the current criteria."
#define ERROR_NEXT_UNREAD_ARTICLE \
"There are no further unread articles in this newsgroup."
#define ERROR_PREV_UNREAD_ARTICLE \
"There are no previous unread articles in this newsgroup."
#define ERROR_NEXT_THREAD_ARTICLE \
np->show_all_articles ? \
"There are no further articles on this subject in this newsgroup." \
: \
"No further UNREAD articles on this subject in this newsgroup."
#define ERROR_PREV_THREAD_ARTICLE \
np->show_all_articles ? \
"There are no previous articles on this subject in this newsgroup." \
: \
"No previous UNREAD articles on this subject in this newsgroup."
#define ERROR_FIRST_THREAD_ARTICLE \
np->show_all_articles ? \
"No other article could be found on this subject in this newsgroup." \
: \
"No UNREAD article could be found on this subject in this newsgroup."
#define ERROR_LAST_THREAD_ARTICLE \
np->show_all_articles ? \
"No other article could be found on this subject in this newsgroup." \
: \
"No UNREAD article could be found on this subject in this newsgroup."
#define ERROR_NEW_THREAD_ARTICLE \
"There are no unread articles on other subjects in this newsgroup."
enum getop_option {
GETOP_NOMORE,
GETOP_ASIS,
GETOP_UPPERCASE,
GETOP_LOWERCASE,
GETOP_INTEGER
};
/****** Get the next operand of the command. *************************/
static Bool
getop(np,bufpp,argp,option)
Rstruc nncb *np;
char **bufpp;
char *argp;
enum getop_option option;
{
register char *icp;
register char *ocp;
register int olen;
int maxlen;
char quote;
char work[12];
icp = skip_ISPF_whitespace(*bufpp);
if (!*icp) { /* if reached end of buffer */
*bufpp = icp;
switch (option) {
case GETOP_NOMORE: return TRUE; /* indicate no more */
case GETOP_INTEGER: ERR1("A numeric integer value is required.");
return FALSE;
default: *argp = '\0'; /* set operand to null string*/
return TRUE;
}
}
/* icp points to next argument in buffer */
if (option == GETOP_NOMORE) return FALSE; /* too many operands */
if (option == GETOP_INTEGER) {
ocp = work;
maxlen = sizeof(work);
quote = '\0';
}
else {
ocp = argp;
maxlen = ARGSIZE;
switch (*icp) {
case '\'':
case '"' : quote = *icp; break;
default: quote = '\0'; break;
}
}
if (quote) {
for (icp++,olen=0; ; icp++,ocp++,olen++) {
if (!*icp) {
ERR1("Beginning quote mark not matched by ending quote mark.");
*bufpp = icp;
return FALSE;
}
if (*icp == quote) {
if (*(++icp) != quote) {
*bufpp = icp;
break;
}
}
if (olen <= maxlen) {
switch (option) {
case GETOP_LOWERCASE: *ocp = tolower(*icp); break;
case GETOP_UPPERCASE: *ocp = toupper(*icp); break;
default: *ocp = *icp; break;
}
}
}
if (olen > maxlen) {
ERR2("An operand longer than %d characters is not valid.", maxlen);
return FALSE;
}
}
else {
find_ISPF_whitespace(*bufpp,icp);
olen = *bufpp - icp;
if (olen > maxlen) {
ERR2("An operand longer than %d characters is not valid.", maxlen);
return FALSE;
}
switch (option) {
case GETOP_LOWERCASE: while (olen--) *ocp++ = tolower(*icp++);
break;
case GETOP_UPPERCASE: while (olen--) *ocp++ = toupper(*icp++);
break;
default: while (olen--) *ocp++ = *icp++;
break;
}
}
*ocp = '\0';
if (option == GETOP_INTEGER) {
if (*(work + strspn(work,"0123456789"))) {
ERR1("A numeric integer value is required.");
return FALSE;
}
*(int *)argp = atoi(work);
}
return TRUE;
}
/****** Subject compare, for locating by subject. ********************/
/* May want to emulate NNMstrlc for more efficiency. All that is
* needed is to add code to NNMstrlc to strip re's.
*/
static int
subjectcmp(a,b)
char *a;
char *b;
{
char *c1;
char *c2;
int re_count_1;
int re_count_2;
int answer;
char s2[257];
/* arg 1 already lowercased */
strncpy(s2,b,256);
lowercase_and_strip_trailing_in_place(s2);
c1 = a;
c2 = s2;
re_count_1 = 0;
while (!memcmp(c1,"re:",3)) {
c1 = skip_whitespace(c1+3);
re_count_1++;
}
re_count_2 = 0;
while (!memcmp(c2,"re:",3)) {
c2 = skip_whitespace(c2+3);
re_count_2++;
}
if ((answer=strcmp(c1,c2)) != 0) return answer;
else return re_count_1 - re_count_2;
}
/****** Mark all articles read. **************************************/
static Bool
mark_all_articles_read(np,gp,prompt)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Fool prompt;
{
int prc;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
/* Display panel asking if user really wants to do this. */
if (prompt && !np->batch_mode) {
(void)NNMivput(np,"NNMARK ","Read",-1);
(void)NNMispf(np,"ADDPOP");
prc = NNMdispl(np,"NNMPMARK");
(void)NNMispf(np,"REMPOP");
if (prc > 0) { /* see if user pressed END */
WARN1("Operation cancelled, because you pressed END.");
return TRUE;
}
}
if (gp->article_vector) {
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
SetRead(*vp);
}
}
else { /* no article vector, group was never selected */
if (gp->saved_newsrc_line
&& gp->saved_newsrc_line != gp->saved_newsrc_data) {
FREEMAIN(gp->saved_newsrc_line,"unparsed newsrc line");
}
gp->saved_newsrc_line = gp->saved_newsrc_data;
sprintf(gp->saved_newsrc_data,"<%d",gp->high_number);
}
gp->unread_count = 0;
WARN2("All of the articles in %s are now marked READ.",
gp->name);
return TRUE;
}
/****** Mark all articles unread. ************************************/
static Bool
mark_all_articles_unread(np,gp,prompt)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Fool prompt;
{
int prc;
int uc;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
/* Display panel asking if user really wants to do this. */
if (prompt && !np->batch_mode) {
(void)NNMivput(np,"NNMARK ","Unread",-1);
(void)NNMispf(np,"ADDPOP");
prc = NNMdispl(np,"NNMPMARK");
(void)NNMispf(np,"REMPOP");
if (prc > 0) { /* see if user pressed END */
WARN1("Operation cancelled, because you pressed END.");
return TRUE;
}
}
if (gp->article_vector) {
uc = 0;
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
/* Note that we don't mark missing articles unread. */
if (IsPresent(*vp)) {
if (IsRead(*vp)) uc++;
SetUnread(*vp);
}
}
gp->unread_count += uc;
}
else { /* no article vector, group was never selected */
if (gp->saved_newsrc_line
&& gp->saved_newsrc_line != gp->saved_newsrc_data) {
FREEMAIN(gp->saved_newsrc_line,"unparsed newsrc line");
}
gp->saved_newsrc_line = gp->saved_newsrc_data;
strcpy(gp->saved_newsrc_data,"<0");
gp->unread_count = gp->article_count;
}
WARN2("All of the articles in %s are now marked UNREAD.",
gp->name);
return TRUE;
}
/****** Set subject. *************************************************/
static char *
set_subject(np,subj)
Rstruc nncb *np;
char *subj;
{
char *s;
if (*np->selsubj) return np->selsubj;
strncpy(np->selsubj, subj, sizeof(np->selsubj)-1);
s = np->selsubj;
lowercase_and_strip_trailing_in_place(s);
while (!memcmp(s,"re:",3)) {
s = skip_whitespace(s+3);
}
return s;
}
/****** Process newsgroup LOCATE command. ****************************/
static Bool
newsgroup_locate_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
char string[ARGSIZE];
/*
* Pass back the group name to position to. NNMVNG will do the rest.
*/
if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
if (!*string || !getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The LOCATE command requires exactly one operand.");
return FALSE;
}
strcpy(np->newsgroup_locate_string, string);
np->please_locate_group = TRUE;
return TRUE;
}
/****** Process newsgroup ONLY command. ******************************/
static Bool
newsgroup_only_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
char string[ARGSIZE];
if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1(
"The ONLY command may have only one operand. Try quoting the string."
);
return FALSE;
}
strcpy(np->newsgroup_only_string, string);
np->newsgroup_criterion_changed = TRUE;
if (*np->newsgroup_only_string) {
WARN2(
"To redisplay %s newsgroups, use ONLY command without operands.",
(np->show_all_newsgroups ? "all" : "all registered"));
}
return TRUE;
}
/****** Process newsgroup FIND command. ******************************/
static Bool
newsgroup_find_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
Bool string_given;
Bool option_given;
char string [ARGSIZE];
char opt [ARGSIZE];
/*
* Pass back the group name to position to. NNMVNG will do the rest.
*/
if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
if (!getop(np,&rest,&opt ,GETOP_LOWERCASE)) return FALSE;
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1(
"Too many operands on the FIND command. Try quoting the string.");
return FALSE;
}
string_given = *string;
option_given = *opt;
if (string_given) {
strcpy(np->newsgroup_find_string,string);
}
else if (!*np->newsgroup_find_string) {
ERR1(
"The FIND command requires a string the first time it is used.");
return FALSE;
}
if (option_given) {
if (EQUAL(opt,"next" )) np->newsgroup_find_option = FIND_NEXT;
else if (EQUAL(opt,"first" )) np->newsgroup_find_option = FIND_FIRST;
else if (EQUAL(opt,"prev" )) np->newsgroup_find_option = FIND_PREV;
else if (EQUAL(opt,"last" )) np->newsgroup_find_option = FIND_LAST;
else {
ERR1("Unknown FIND option. Specify NEXT, PREV, FIRST or LAST.");
return FALSE;
}
}
else {
if (string_given) np->newsgroup_find_option = FIND_NEXT;
else switch (np->newsgroup_find_option) {
case FIND_NEXT: np->newsgroup_find_option = FIND_NEXT; break;
case FIND_PREV: np->newsgroup_find_option = FIND_PREV; break;
case FIND_FIRST: np->newsgroup_find_option = FIND_NEXT; break;
case FIND_LAST: np->newsgroup_find_option = FIND_PREV; break;
default: np->newsgroup_find_option = FIND_NEXT; break;
}
}
np->please_find_group = TRUE;
np->repeat_find = (!string_given && !option_given);
return TRUE;
}
/****** Process newsgroup EXTRACT command. ***************************/
static Bool
newsgroup_extract_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The EXTRACT command does not accept any operands.");
return FALSE;
}
return NNMxlist(np,SEQ); /* Extract newsgroup listing */
}
/****** Process newsgroup PRINT command. *****************************/
static Bool
newsgroup_print_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The PRINT command does not accept any operands.");
return FALSE;
}
return NNMxlist(np,JES); /* Extract newsgroup listing */
}
/****** Process newsgroup REG command. *******************************/
static Bool
newsgroup_reg_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
np->newsgroup_criterion_changed = TRUE;
np->show_all_newsgroups = FALSE;
if (*np->newsgroup_only_string) {
WARN2(
"To redisplay %s newsgroups, use ONLY command without operands.",
(np->show_all_newsgroups ? "all" : "all registered"));
}
return TRUE;
}
/****** Process newsgroup ALL command. *******************************/
static Bool
newsgroup_all_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
np->newsgroup_criterion_changed = TRUE;
np->show_all_newsgroups = TRUE;
if (*np->newsgroup_only_string) {
WARN2(
"To redisplay %s newsgroups, use ONLY command without operands.",
(np->show_all_newsgroups ? "all" : "all registered"));
}
return TRUE;
}
/****** Process newsgroup ORDER command. *****************************/
static Bool
newsgroup_order_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
char string[ARGSIZE];
char order;
/* Usage: ORDER A - display newsgroups in alphabetical order
* ORDER L - display newsgroups in NNTP list order
* ORDER N - display newsgroups in NEWSRC order
*/
if (!getop(np,&rest,&string,GETOP_ASIS)) return FALSE;
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1(
"The ORDER command requires one operand: Alphabetical or List.");
return FALSE;
}
switch (string[0]) {
case 'a':
case 'A': order = ALPHABETICAL_ORDER; break;
case 'l':
case 'L': order = NNTP_LIST_ORDER; break;
case 'n':
case 'N': order = NEWSRC_ORDER; break;
default:
ERR1(
"The ORDER command requires one operand: Alphabetical or List.");
return FALSE;
}
if (order == NEWSRC_ORDER) {
ERR1("Sorry, but NEWSRC order has not been implemented.");
return FALSE;
}
if (order == NNTP_LIST_ORDER && !np->first_newsgroup_alt) {
ERR1(
"List order is valid only when newsgroup list retrieved from server."
);
return FALSE;
}
np->newsgroup_order_changed = TRUE;
np->newsgroup_order = order;
return TRUE;
}
/****** Process article LOCATE command. ******************************/
static Bool
article_locate_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
struct newsarticle *ap;
VARK **wp;
VARK **wpfirst;
VARK **wplast;
int lnum;
struct countdown cd;
char string[ARGSIZE];
if (gp->sort_vector) {
if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
if (!*string || !getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The LOCATE command requires exactly one operand.");
return FALSE;
}
/* Position to article with subject closest to requested subject */
wpfirst = gp->sort_vector;
wplast = gp->sort_vector + gp->sort_count - 1;
for (wp = wpfirst; wp < wplast; wp++) {
if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)
&& subjectcmp(string,ap->subject) <= 0)
break;
}
np->current_sortvark = wp;
np->top_sorted_article = wp;
}
else {
if (!getop(np,&rest,(char *)&lnum,GETOP_INTEGER)) return FALSE;
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The LOCATE command requires exactly one operand.");
return FALSE;
}
/* Position to article with number closest to requested number */
if (lnum < gp->vector_first) lnum = gp->vector_first;
if (lnum > gp->vector_last) lnum = gp->vector_last;
np->top_article = lnum;
}
/* Note: We don't worry about whether that article, or any of the
* articles between the current one and this one, are in the table.
* When NNMvar regenerates the display, it will know that the top
* article has changed and will figure it out.
*/
return TRUE;
}
/****** Process article FIND command. ********************************/
static Bool
article_find_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
int save_top_article;
VARK **save_top_sorted_article;
struct newsarticle *ap;
VARK **wp;
VARK **wpfirst;
VARK **wplast;
VARK **found_sorted_article;
int found_article;
int findbump;
int anum;
Bool string_given;
Bool option_given;
char string [ARGSIZE];
char option [ARGSIZE];
struct countdown cd;
if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
if (!getop(np,&rest,&option,GETOP_LOWERCASE)) return FALSE;
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1(
"Too many operands on the FIND command. Try quoting the string.");
return FALSE;
}
string_given = *string;
option_given = *option;
if (string_given) {
strcpy(np->article_find_string,string);
}
else if (!*np->article_find_string) {
ERR1(
"The FIND command requires a string the first time it is used.");
return FALSE;
}
if (option_given) {
if (EQUAL(option,"next" )) np->article_find_option = FIND_NEXT;
else if (EQUAL(option,"first")) np->article_find_option = FIND_FIRST;
else if (EQUAL(option,"prev" )) np->article_find_option = FIND_PREV;
else if (EQUAL(option,"last" )) np->article_find_option = FIND_LAST;
else {
ERR1("Unknown FIND option. Specify NEXT, PREV, FIRST or LAST.");
return FALSE;
}
}
else {
if (string_given) np->article_find_option = FIND_NEXT;
else switch (np->article_find_option) {
case FIND_NEXT: np->article_find_option = FIND_NEXT; break;
case FIND_PREV: np->article_find_option = FIND_PREV; break;
case FIND_FIRST: np->article_find_option = FIND_NEXT; break;
case FIND_LAST: np->article_find_option = FIND_PREV; break;
default: np->article_find_option = FIND_NEXT; break;
}
}
np->article_repeat_find = !string_given;
/* do the find here */
if (gp->sort_vector) {
save_top_sorted_article = np->top_sorted_article;
wpfirst = gp->sort_vector;
wplast = gp->sort_vector + gp->sort_count - 1;
switch (np->article_find_option) {
case FIND_NEXT:
findbump = 1;
if (np->article_repeat_find) {
if (np->article_text_not_found)
np->top_sorted_article = wpfirst;
else np->top_sorted_article++;
}
break;
case FIND_PREV:
findbump = -1;
if (np->article_repeat_find) {
if (np->article_text_not_found)
np->top_sorted_article = wplast;
else np->top_sorted_article--;
}
break;
case FIND_FIRST:
np->top_sorted_article = wpfirst;
findbump = 1;
break;
case FIND_LAST:
np->top_sorted_article = wplast;
findbump = -1;
break;
}
found_sorted_article = NULL;
for (wp = np->top_sorted_article;
wp <= wplast && wp >= wpfirst; wp += findbump) {
/* ap = VARK2PARTICLE(**wp); */
if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)
&& NNMstrlc(ap->subject,np->article_find_string)) {
found_sorted_article = wp;
break;
}
}
if (!found_sorted_article) {
np->top_sorted_article = save_top_sorted_article;
np->article_text_not_found = TRUE;
}
else {
np->top_sorted_article = found_sorted_article;
np->article_text_not_found = FALSE;
}
}
else { /* not sorted */
save_top_article = np->top_article;
switch (np->article_find_option) {
case FIND_NEXT:
findbump = 1;
if (np->article_repeat_find) {
if (np->article_text_not_found)
np->top_article = gp->vector_first;
else np->top_article++;
}
break;
case FIND_PREV:
findbump = -1;
if (np->article_repeat_find) {
if (np->article_text_not_found)
np->top_article = gp->vector_last;
else np->top_article--;
}
break;
case FIND_FIRST:
np->top_article = gp->vector_first;
findbump = 1;
break;
case FIND_LAST:
np->top_article = gp->vector_last;
findbump = -1;
break;
}
if (!np->top_article) return FALSE;
cd.do_update = (np->updatefreq >= 0);
cd.done = 0;
cd.to_do = -1;
found_article = 0;
for (anum = np->top_article;
anum <= gp->vector_last && anum >= gp->vector_first;
anum += findbump) {
if (NNMcar(np,gp,anum,NULL,&ap,&cd,RETRIEVE)
&& NNMstrlc(ap->subject,np->article_find_string)) {
found_article = anum;
break;
}
}
if (found_article == 0) {
np->top_article = save_top_article;
np->article_text_not_found = TRUE;
}
else {
np->top_article = found_article;
np->article_text_not_found = FALSE;
}
}
if (np->article_text_not_found) {
ERR3("No %s articles with subject of: '%s'",
(findbump > 0 ? "more" : "previous"),
np->article_find_string);
}
else {
WARN1("Article found;\
The article whose subject contains the desired text tops the display.");
}
return TRUE;
}
/****** Process article ONLY command. *******************************/
static Bool
article_only_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
char string[ARGSIZE];
VARK *vp;
VARK *vpfirst;
VARK *vplast;
if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1(
"The ONLY command may have only one operand. Try quoting the string."
);
return FALSE;
}
strcpy(np->article_only_string, string);
if (gp->article_vector) {
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
SetUnknown(*vp);
}
}
np->article_criterion_changed = TRUE;
np->top_article = gp->vector_first;
np->top_sorted_article = gp->sort_vector;
if (*np->article_only_string) {
WARN1(
"To show articles with all subjects, use ONLY command with no operand."
);
}
return TRUE;
}
/****** Process article SORT command. *******************************/
static Bool
article_sort_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
Bool by_subject;
char string[ARGSIZE];
/* Usage: SORT Subject
* SORT Number
*/
if (!getop(np,&rest,&string,GETOP_ASIS)) return FALSE;
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The SORT command requires one operand: Subject or Number.");
return FALSE;
}
switch (string[0]) {
case 's':
case 'S': by_subject = TRUE; break;
case 'n':
case 'N': by_subject = FALSE; break;
default:
ERR1("The SORT command requires one operand: Subject or Number.");
return FALSE;
}
if (!gp->article_vector) {
ERR1("There are no articles in this newsgroup to sort.");
return TRUE;
}
if (by_subject) {
if (!NNMsort(np,gp)) return FALSE;
}
else {
if (gp->sort_vector) {
FREEMAIN(gp->sort_vector,"sort vector");
gp->sort_vector = NULL;
}
}
np->article_criterion_changed = TRUE;
np->top_article = 0;
np->top_sorted_article = gp->sort_vector;
return TRUE;
}
/****** Process article EXTRACT command. *****************************/
static Bool
article_extract_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
Bool asked_for;
char nnchoice[2];
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The EXTRACT command does not accept any operands.");
return FALSE;
}
(void)NNMivput(np,"NNLGROUP ",gp->name,-1);
/* Display panel asking whether it's list of titles or log of text */
asked_for = TRUE;
(void)NNMispf(np,"ADDPOP");
for (;;) {
if (NNMdispl(np,"NNMPEXNT") > 0) {
asked_for = FALSE;
break;
}
(void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
if (*nnchoice == '?') {
ERR1("Invalid choice;\
Move the cursor to a selection (or type S next to it) and press ENTER."
);
}
else break;
}
(void)NNMispf(np,"REMPOP");
if (!asked_for) return TRUE;
switch (*nnchoice) {
case '1': return NNMxartt(np,gp,SEQ);
case '2': return NNMxartx(np,gp,SEQ);
case '3': return NNMxartx(np,gp,PDS);
}
return FALSE;
}
/****** Process article PRINT command. *******************************/
static Bool
article_print_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
Bool asked_for;
char nnchoice[2];
if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
ERR1("The PRINT command does not accept any operands.");
return FALSE;
}
(void)NNMivput(np,"NNLGROUP ",gp->name,-1);
/* Display panel asking whether it's list of titles or log of text */
asked_for = TRUE;
(void)NNMispf(np,"ADDPOP");
for (;;) {
if (NNMdispl(np,"NNMPPRNT") > 0) {
asked_for = FALSE;
break;
}
(void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
if (*nnchoice == '?') {
ERR1("Invalid choice;\
Move the cursor to a selection (or type S next to it) and press ENTER."
);
}
else break;
}
(void)NNMispf(np,"REMPOP");
if (!asked_for) return TRUE;
switch (*nnchoice) {
case '1': return NNMxartt(np,gp,JES);
case '2': return NNMxartx(np,gp,JES);
}
return FALSE;
}
/****** Process article MARKALL command. *****************************/
static Bool
article_markall_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
struct newsarticle *ap;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
int prc;
Bool allp;
struct countdown cd;
char nnchoice[9];
cd.do_update = (np->updatefreq >= 0);
cd.done = 0;
cd.to_do = -1;
if (!gp->article_vector) {
ERR1("There are no articles to mark.");
return TRUE;
}
/* Display panel asking what user really wants to do. */
strcpy(nnchoice,"");
for (;;) {
(void)NNMivput(np,"NNMARK ","Read",-1);
(void)NNMispf(np,"ADDPOP");
prc = NNMdispl(np,"NNMPMALL");
(void)NNMispf(np,"REMPOP");
if (prc > 0) strcpy(nnchoice,"3");
else (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
switch (nnchoice[0]) {
case '1': allp = TRUE; break;
case '2': allp = FALSE; break;
case '3': ERR1("Operation cancelled by your request.");
return TRUE;
default:
ERR1("Invalid choice;\
Move the cursor to a selection (or type S next to it) and press ENTER."
);
continue;
}
break;
}
/*
* This isn't really too good. It means that ALL the articles
* will have to be retrieved in order to mark them read.
*
* A better way would be to set a flag in the VARK saying
* "marked read" rather than "read", so that future fetches
* would put the article in the table but set the action to
* "read". We're going to need a "cross-posted-read" flag
* that's independent of fetching the article anyhow...
*
* How about this? Add a new article status, ARTICLE_DUMMY,
* set when unique storage is allocated for a struct newsarticle
* but neither the headers nor the body have been retrieved.
* It would have null values in it, but:
*
* the action field could be set when article is marked (un)read
* the subject field could be set from an XHDR request
* likewise for date, etc. fields
*
* If NNMrarh is asked to retrieve such an article, it will fill
* it in with stuff.
*
* NNMcar could be modified to be asked to create dummy articles
* instead of retrieving headers for them. This would be done if
* just going through and setting ap->actions or ap->subjects.
*/
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
if (allp) {
mark_all_articles_read(np,gp,FALSE);
for (vp = vpfirst; vp <= vplast; vp++) {
if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
if (ap) ap->action = READ;
}
}
gp->unread_count = 0;
}
else {
for (vp = vpfirst; vp <= vplast; vp++) {
if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
NNMmarr(np,gp,vp); /* mark article read */
}
}
}
return TRUE;
}
/****** Process article UNMARKALL command. ***************************/
static Bool
article_unmarkall_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
struct newsarticle *ap;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
int prc;
Bool allp;
char nnchoice[9];
struct countdown cd;
cd.do_update = (np->updatefreq >= 0);
cd.done = 0;
cd.to_do = -1;
if (!gp->article_vector) {
ERR1("There are no articles to mark.");
return TRUE;
}
/* Display panel asking what user really wants to do. */
strcpy(nnchoice,"");
for (;;) {
(void)NNMivput(np,"NNMARK ","Unread",-1);
(void)NNMispf(np,"ADDPOP");
prc = NNMdispl(np,"NNMPMALL");
(void)NNMispf(np,"REMPOP");
if (prc > 0) strcpy(nnchoice,"3");
else (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
switch (nnchoice[0]) {
case '1': allp = TRUE; break;
case '2': allp = FALSE; break;
case '3': ERR1("Operation cancelled by your request.");
return TRUE;
default:
ERR1("Invalid choice;\
Move the cursor to a selection (or type S next to it) and press ENTER."
);
continue;
}
break;
}
/* see comments under previous function. they apply here too */
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
if (allp) {
mark_all_articles_unread(np,gp,FALSE);
for (vp = vpfirst; vp <= vplast; vp++) {
if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
if (ap) ap->action = UNREAD;
}
}
gp->unread_count = gp->article_count;
}
else {
for (vp = vpfirst; vp <= vplast; vp++) {
if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
NNMmaru(np,gp,vp); /* mark article read */
}
}
}
return TRUE;
}
/****** Process article TITLES command. ******************************/
static Bool
article_titles_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
/* Actually, this probably ought to be a NOP, since we always ought to
* be retrieving article titles as we display a screenful.
* Since this command retrieves ALL titles, it's kind of wasteful.
*/
(void)NNMrart(np,gp,TRUE,TRUE); /* Retrieve *all* article titles */
return TRUE;
}
/****** Process article QUERY command. *******************************/
static Bool
article_query_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
NNMqng(np,gp); /* Query newsgroup */
return TRUE;
}
/****** Process POST command. ****************************************/
static Bool
general_post_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
NNMdpost(np,gp,NULL); /* Do posting (no article up to follow) */
return TRUE;
}
/****** Process MAIL command. ****************************************/
static Bool
general_mail_command(np,gp,rest)
Rstruc nncb *np;
Rstruc newsgroup *gp;
char *rest;
{
NNMdmail(np,gp,NULL); /* Do mailing (no article to to reply) */
return TRUE;
}
/****** Process TEST command. ****************************************/
static Bool
general_test_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
np->test_mode = TRUE;
__ctest(rest);
return TRUE;
}
/****** Process NNTP command. ****************************************/
static Bool
general_nntp_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
(void)NNMdnntp(np,rest); /* Do native NNTP */
return TRUE;
}
/****** Process SAVE command. ****************************************/
static Bool
general_save_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
return NNMsave(np,rest); /* Save NEWSRC file */
}
/****** Process OPTIONS command. *************************************/
static Bool
general_options_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
char option[ARGSIZE];
if (!getop(np,&rest,&option,GETOP_LOWERCASE)) return FALSE;
NNMdsopt(np,option); /* Do "set options" function */
return TRUE;
}
/****** Process QUIT command. ****************************************/
static Bool
general_quit_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
np->quit = TRUE;
return TRUE;
}
/****** Process CRASHNNMVS command. **********************************/
static Bool
general_crashnnmvs_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
fprintf(stderr,"Terminating NNMVS with extreme prejudice.\n");
exit(999);
}
/****** Process DEBUG command. ***************************************/
static Bool
general_debug_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
if (!np->debug_mode) {
if (!(np->debug_file = fopen("dd:nndebug","a"))) {
perror("debug file (DD NNDEBUG)");
}
else np->debug_mode = TRUE;
}
return TRUE;
}
/****** Process NODEBUG command. *************************************/
static Bool
general_nodebug_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
if (np->debug_mode) {
if (np->debug_file) {
if (fclose(np->debug_file) < 0) {
fprintf(stderr,"Error closing debug file (DD NNDEBUG)\n");
}
np->debug_file = NULL;
}
np->debug_mode = FALSE;
}
return TRUE;
}
/****** Process DISCONNECT command. *********************************/
static Bool
general_disconnect_command(np,gp,rest)
Rstruc nncb *np;
struct newsgroup *gp;
char *rest;
{
char *dummy = "503 Simulated disconnect.";
int index;
/* fake a disconnect condition by sending an NNTP "QUIT".
* The next attempt to communicate with the socket will get
* the simulated response instead of what it expected.
*/
strcpy(np->nntp_command,"QUIT");
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
index = strlen(dummy);
strcpy(np->g_buf+1,dummy);
np->g_buf[index+1] = CARRIAGE_RETURN;
np->g_buf[index+2] = LINE_FEED;
np->g_bytes_returned = index+3;
np->g_buf_index = 0;
return TRUE;
}
/****** Process newsgroup S selection. *******************************/
static Bool
newsgroup_s_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
np->show_all_articles = FALSE;
np->bypass_header_retrieval = FALSE;
np->unread_articles_only = FALSE;
return(NNMpng(np,gp,FALSE,FALSE)); /* Pick newsgroup */
}
/****** Process newsgroup N selection. *******************************/
static Bool
newsgroup_n_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
np->show_all_articles = FALSE;
np->bypass_header_retrieval = FALSE;
np->unread_articles_only = TRUE;
return(NNMpng(np,gp,FALSE,FALSE)); /* Pick newsgroup */
}
/****** Process newsgroup A selection. *******************************/
static Bool
newsgroup_a_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
np->show_all_articles = TRUE;
np->bypass_header_retrieval = FALSE;
np->unread_articles_only = FALSE;
return(NNMpng(np,gp,FALSE,FALSE)); /* Pick newsgroup */
}
/****** Process newsgroup Z selection. *******************************/
static Bool
newsgroup_z_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
np->show_all_articles = TRUE;
np->bypass_header_retrieval = TRUE;
np->unread_articles_only = FALSE;
return(NNMpng(np,gp,FALSE,FALSE)); /* Pick newsgroup */
}
/****** Process newsgroup $ selection. *******************************/
static Bool
newsgroup_dollar_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
np->show_all_articles = FALSE;
np->bypass_header_retrieval = FALSE;
np->unread_articles_only = FALSE;
return(NNMpng(np,gp,TRUE,TRUE)); /* pick group, get titles, sort it */
}
/****** Process newsgroup @ selection. *******************************/
static Bool
newsgroup_atsign_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
np->show_all_articles = TRUE;
np->bypass_header_retrieval = FALSE;
np->unread_articles_only = FALSE;
return(NNMpng(np,gp,TRUE,TRUE)); /* pick group, get titles, sort it */
}
/****** Process newsgroup Q selection. *******************************/
static Bool
newsgroup_q_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
NNMqng(np,gp); /* Query newsgroup */
return TRUE;
}
/****** Process newsgroup R selection. *******************************/
static Bool
newsgroup_r_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
gp->registered = 1;
WARN2("Newsgroup %s registered (subscribed).", gp->name);
return TRUE;
}
/****** Process newsgroup D selection. *******************************/
static Bool
newsgroup_d_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
gp->registered = 0;
WARN2("Newsgroup %s deregistered (unsubscribed).", gp->name);
return TRUE;
}
/****** Process newsgroup M selection. *******************************/
static Bool
newsgroup_m_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
return mark_all_articles_read(np,gp,TRUE);
}
/****** Process newsgroup U selection. *******************************/
static Bool
newsgroup_u_selection(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
return mark_all_articles_unread(np,gp,TRUE);
}
/****** Process article E selection. *********************************/
static Bool
article_e_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
np->extract_file = NULL;
if (!NNMpick(np,ap)) return FALSE;
NNMdoit(np,ap,'E');
return TRUE;
}
/****** Process article F selection. *********************************/
static Bool
article_f_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
if (!NNMpick(np,ap)) return FALSE;
NNMdoit(np,ap,'F');
return TRUE;
}
/****** Process article C selection. *********************************/
static Bool
article_c_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
if (!NNMpick(np,ap)) return FALSE;
NNMdoit(np,ap,'C');
return TRUE;
}
/****** Process article M selection. *********************************/
static Bool
article_m_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
Rstruc newsgroup *gp = np->current_newsgroup;
VARK *vp = &GETVARK(gp,ap->number);
NNMmarr(np,gp,vp); /* Make article read */
return TRUE;
}
/****** Process article P selection. *********************************/
static Bool
article_p_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
np->extract_file = NULL;
if (!NNMpick(np,ap)) return FALSE;
NNMdoit(np,ap,'P');
return TRUE;
}
/****** Process article Q selection. *********************************/
static Bool
article_q_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
return NNMqar(np,ap);
}
/****** Process article R selection. *********************************/
static Bool
article_r_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
if (!NNMpick(np,ap)) return FALSE;
NNMdoit(np,ap,'R');
return TRUE;
}
/****** Process article S selection. *********************************/
static Bool
article_s_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
Rstruc newsgroup *gp = np->current_newsgroup;
Rstruc newsarticle *ap1 = ap;
Rstruc newsarticle *ap2 = NULL;
VARK *vp;
VARK *vp1;
enum article_cookie cookie;
Bool save_show_all_articles;
struct countdown cd;
np->extract_file = NULL;
clear_subject(np);
/* Continue as long as NEXT/PREV/UNREAD requests occur. */
for (;;) {
if (!NNMpick(np,ap1)) return FALSE; /* Pick article to process */
NNMdoit(np,ap1,'S'); /* Process article */
cookie = np->another_article;
if (cookie == NULL_ARTICLE_COOKIE) break;
cd.do_update = (np->updatefreq >= 0);
cd.done = 0;
cd.to_do = -1;
switch (cookie) {
case REDISPLAY_ARTICLE:
ap2 = NULL;
break;
case UNREAD_THIS_ARTICLE:
clear_subject(np);
vp1 = &GETVARK(gp,ap1->number);
NNMmaru(np,gp,vp1); /* Make article unread */
return TRUE;
case NEXT_ARTICLE:
save_show_all_articles = np->show_all_articles;
np->show_all_articles = TRUE;
SEARCH_CURRENT_TO_LAST(ap2,ap1,NOTHING,NO_COMPARISON,ANY);
np->show_all_articles = save_show_all_articles;
if (!ap2) ERR1(ERROR_NEXT_ARTICLE);
break;
case PREV_ARTICLE:
save_show_all_articles = np->show_all_articles;
np->show_all_articles = TRUE;
SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOTHING,NO_COMPARISON,ANY);
np->show_all_articles = save_show_all_articles;
if (!ap2) ERR1(ERROR_PREV_ARTICLE);
break;
case NEXT_TABLED_ARTICLE:
SEARCH_CURRENT_TO_LAST(ap2,ap1,NOTHING,IsEligible(*vp),NO);
if (!ap2) ERR1(ERROR_NEXT_TABLED_ARTICLE);
break;
case PREV_TABLED_ARTICLE:
SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOTHING,IsEligible(*vp),NO);
if (!ap2) ERR1(ERROR_PREV_TABLED_ARTICLE);
break;
case NEXT_UNREAD_ARTICLE:
SEARCH_CURRENT_TO_LAST(ap2,ap1,NOTHING,IsUnread(*vp),NO);
if (!ap2) ERR1(ERROR_NEXT_UNREAD_ARTICLE);
break;
case PREV_UNREAD_ARTICLE:
SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOTHING,IsUnread(*vp),NO);
if (!ap2) ERR1(ERROR_PREV_UNREAD_ARTICLE);
break;
case NEXT_THREAD_ARTICLE:
SEARCH_CURRENT_TO_LAST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
if (!ap2) {
ERR1(ERROR_NEXT_THREAD_ARTICLE);
clear_subject(np);
}
break;
case PREV_THREAD_ARTICLE:
SEARCH_CURRENT_TO_FIRST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
if (!ap2) {
ERR1(ERROR_PREV_THREAD_ARTICLE);
clear_subject(np);
}
break;
case FIRST_THREAD_ARTICLE:
SEARCH_FIRST_TO_LAST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
if (!ap2) {
ERR1(ERROR_FIRST_THREAD_ARTICLE);
clear_subject(np);
}
break;
case LAST_THREAD_ARTICLE:
SEARCH_LAST_TO_FIRST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
if (!ap2) {
ERR1(ERROR_LAST_THREAD_ARTICLE);
clear_subject(np);
}
break;
case NEW_THREAD_ARTICLE:
SEARCH_FIRST_TO_LAST(ap2,ap1,SETSUBJECT,
IsUnread(*vp) && !subjectmatch,NO);
clear_subject(np);
if (!ap2) ERR1(ERROR_NEW_THREAD_ARTICLE);
else (void)set_subject(np,ap2->subject);
break;
default:
clear_subject(np);
ap2 = NULL;
break;
}
if (ap2) {
/* Bump display to article to be seen */
if (gp->sort_vector)
np->top_sorted_article = np->current_sortvark;
else np->top_article = ap2->number;
SetEligible(*vp); /* Force it eligible for display */
ap1 = ap2;
}
}
clear_subject(np);
return TRUE;
}
/****** Process article U selection. *********************************/
static Bool
article_u_selection(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
Rstruc newsgroup *gp = np->current_newsgroup;
VARK *vp = &GETVARK(gp,ap->number);
NNMmaru(np,gp,vp); /* Make article unread */
return TRUE;
}
/*********************************************************************/
void
NNMinit(np)
Rstruc nncb *np;
{
static struct tabledesc newsgroup_display_table;
static struct tabledesc article_display_table;
static struct tabledesc text_display_table;
static struct cmddesc newsgroup_commands[] = {
{"L ",newsgroup_locate_command },
{"LOC ",newsgroup_locate_command },
{"LOCATE ",newsgroup_locate_command },
{"F ",newsgroup_find_command },
{"FIND ",newsgroup_find_command },
{"EXT ",newsgroup_extract_command },
{"EXTRACT ",newsgroup_extract_command },
{"PRT ",newsgroup_print_command },
{"PRNT ",newsgroup_print_command },
{"REG ",newsgroup_reg_command },
{"REGISTER ",newsgroup_reg_command },
{"ALL ",newsgroup_all_command },
{"ONLY ",newsgroup_only_command },
{"ORDER ",newsgroup_order_command },
{" ",NULL}
};
static struct cmddesc article_commands[] = {
{"L ",article_locate_command },
{"LOC ",article_locate_command },
{"LOCATE ",article_locate_command },
{"F ",article_find_command },
{"FIND ",article_find_command },
{"EXT ",article_extract_command },
{"EXTRACT ",article_extract_command },
{"PRT ",article_print_command },
{"PRNT ",article_print_command },
{"MARKALL ",article_markall_command },
{"UNMARKALL ",article_unmarkall_command },
{"TITLE ",article_titles_command },
{"TITLES ",article_titles_command },
{"ONLY ",article_only_command },
{"Q ",article_query_command },
{"QUERY ",article_query_command },
{"SORT ",article_sort_command },
{" ",NULL}
};
static struct cmddesc general_commands[] = {
{"POST ",general_post_command },
{"MAIL ",general_mail_command },
{"TEST ",general_test_command },
{"NNTP ",general_nntp_command },
{"SAVE ",general_save_command },
{"OPTIONS ",general_options_command },
{"OPT ",general_options_command },
{"QUIT ",general_quit_command },
{"DEBUG ",general_debug_command },
{"NODEBUG ",general_nodebug_command },
{"DISCONNECT ",general_disconnect_command },
{"CRASHNNMVS ",general_crashnnmvs_command },
{" ",NULL}
};
static struct seldesc newsgroup_selections[] = {
{'S',newsgroup_s_selection },
{'N',newsgroup_n_selection },
{'A',newsgroup_a_selection },
{'R',newsgroup_r_selection },
{'D',newsgroup_d_selection },
{'M',newsgroup_m_selection },
{'U',newsgroup_u_selection },
{'Q',newsgroup_q_selection },
/* {'Z',newsgroup_z_selection }, */
{'$',newsgroup_dollar_selection },
{'@',newsgroup_atsign_selection },
{' ',NULL}
};
static struct seldesc article_selections[] = {
{'S',article_s_selection },
{'E',article_e_selection },
{'P',article_p_selection },
{'M',article_m_selection },
{'U',article_u_selection },
{'F',article_f_selection },
{'R',article_r_selection },
{'Q',article_q_selection },
{'C',article_c_selection },
{' ',NULL}
};
static struct tablevector all_display_tables;
newsgroup_display_table.command_variable = "NNGCMD ";
newsgroup_display_table.first_cmddesc = newsgroup_commands;
newsgroup_display_table.next_cmddesc = general_commands;
newsgroup_display_table.first_seldesc = newsgroup_selections;
article_display_table.command_variable = "NNTCMD ";
article_display_table.first_cmddesc = article_commands;
article_display_table.next_cmddesc = general_commands;
article_display_table.first_seldesc = article_selections;
text_display_table.command_variable = "ZCMD ";
text_display_table.first_cmddesc = NULL; /* filled later */
text_display_table.next_cmddesc = general_commands;
text_display_table.first_seldesc = NULL;
all_display_tables.newsgroup_display_table = &newsgroup_display_table;
all_display_tables.article_display_table = &article_display_table;
all_display_tables.text_display_table = &text_display_table;
np->display_table_vector = &all_display_tables;
return;
}
./ ADD NAME=NNMISPF,SSI=01010058
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ISPF ")
#pragma csect(static,"NN$ISPF ")
#include "nn.h"
/****** Call ISPF service. *******************************************/
Bool
NNMispf(np,ispfbuf)
Rstruc nncb *np;
char *ispfbuf;
{
int ispflen;
ispflen = strlen(ispfbuf);
#ifndef ISPFV2
if (np->test_mode) {
#endif
if (ispflen >= 6
&& (memcmp(ispfbuf,"ADDPOP",6) == 0
|| memcmp(ispfbuf,"REMPOP",6) == 0)) {
np->ispfrc = 0;
return TRUE;
}
#ifndef ISPFV2
}
#endif
np->ispfrc = ISPEXEC(&ispflen,ispfbuf);
if (np->ispfrc > 8) {
/* Ignore ADDPOP and REMPOP errors, especially if they are due to
ISPF V3 not being active. */
if (np->ispfrc == 20
&& np->debug_mode == FALSE
&& ispflen >= 6
&& (memcmp(ispfbuf,"ADDPOP",6) == 0
|| memcmp(ispfbuf,"REMPOP",6) == 0)) {
return TRUE;
}
NNMierr(np); /* handle ISPF error */
return FALSE;
}
return TRUE;
}
./ ADD NAME=NNMIVGET,SSI=01000032
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@IVGET")
#pragma csect(static,"NN$IVGET")
#include "nn.h"
/****** Retrieve the value of an ISPF variable. **********************/
Bool
NNMivget(np,varname,varbuf,varbuflen)
Rstruc nncb *np;
char *varname;
char *varbuf;
int varbuflen;
{
int vcopy_length;
if (!strchr(varname,' ')) {
fprintf(stderr,"NNMivget: no blank passed in var name\n");
return FALSE;
}
/*
* If varbuflen is negative, that means that the value is not to be
* treated as a C string, and the null character is not to be
* appended to the resulting value. This is used for hex values
* (like addresses) that are stored in ISPF table row variables.
*/
if (varbuflen < 0) vcopy_length = -varbuflen;
else vcopy_length = varbuflen;
/* Note that on entry, vcopy_length is an integer that contains
the length of the buffer. On return it is updated to the length
of the value returned. Since we have to stick a null character
on the end of it for C, the actual buffer passed must be at least
one character longer than the length as defined to ISPF.
*/
np->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
switch (np->ispfrc) {
case 0:
if (varbuflen >= 0) varbuf[vcopy_length] = '\0';
return TRUE;
case 8:
strcpy(varbuf,"");
return TRUE;
case 16:
fprintf(stderr,
"Error: ISPF variable buffer too short to get %s\n",
varname);
return FALSE;
default:
NNMierr(np); /* handle ISPF error */
return FALSE;
}
}
./ ADD NAME=NNMIVPUT,SSI=01000043
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@IVPUT")
#pragma csect(static,"NN$IVPUT")
#include "nn.h"
/****** Set the value of an ISPF variable. ***************************/
Bool
NNMivput(np,varname,varbuf,varlen)
Rstruc nncb *np;
char *varname;
char *varbuf;
int varlen;
{
int vreplace_length;
vreplace_length = (varlen < 0 ? strlen(varbuf) : varlen);
np->ispfrc = ISPLINK("VREPLACE",varname,&vreplace_length,varbuf);
switch (np->ispfrc) {
case 0:
return TRUE;
case 16:
fprintf(stderr,
"Error: ISPF variable buffer too short to put %s\n",
varname);
return FALSE;
default:
NNMierr(np); /* handle ISPF error */
return FALSE;
}
}
./ ADD NAME=NNMMAIN,SSI=01020026
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/********************************************************************/
/* */
/* NNMVS */
/* */
/* MVS news reader dialog driver */
/* */
/* Author: */
/* Steve Bacher <seb@draper.com> */
/* */
/* Enhancements contributed by: */
/* Dale Ingold <snoddi@mvs.sas.com> */
/* */
/* Version: 3 Release: 1 */
/* */
/********************************************************************/
#ifdef SASC
#pragma runopts(EXECOPS)
#else
#pragma runopts(heap(8k,8k,anywhere,))
#pragma runopts(nospie,nostae)
#endif
#pragma csect(code, "NN@MAIN ")
#pragma csect(static,"NN$MAIN ")
#include "nn.h"
/*********************************************************************/
static char copyright_notice[] =
"Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 \n\
\n\
SAS enhancements copyright (c) 1992 SAS Institute, Inc. \n\
\n\
This software is provided on an 'AS IS' basis. All warranties, \n\
including the implied warranties of merchantability and fitness,\n\
are expressly denied. \n\
\n\
Provided this copyright notice is included, this software may \n\
be freely distributed and not offered for sale. \n\
\n\
Changes or modifications may be made and used only by the maker \n\
of same, and not further distributed. Such modifications should\n\
be mailed to the author for consideration for addition to the \n\
software and incorporation in subsequent releases.";
/*********************************************************************/
#ifdef I370
char * _style = "tso:";
#endif
/*********************************************************************/
static void
trap_ispf_command(np,verb,action)
Rstruc nncb *np;
char *verb;
char *action;
{
char zcttrunc [16];
char zctact [64];
char zctdesc [128];
if (!NNMivput(np,"ZCTVERB ",verb,-1)) return;
if (!NNMispf(np,"TBTOP ISPCMDS")) return;
if (!NNMispf(np,"TBSCAN ISPCMDS ARGLIST(ZCTVERB)")) return;
if (!NNMivget(np,"ZCTACT ",zctact,sizeof(zctact))) return;
if (UNEQUAL(zctact,action)) {
NNMivget(np,"ZCTTRUNC ",zcttrunc, sizeof(zcttrunc));
NNMivget(np,"ZCTDESC ",zctdesc,sizeof(zctdesc));
if (!NNMispf(np,"TBTOP ISPCMDS ")) return;
NNMivput(np,"ZCTACT ",action ,-1);
NNMivput(np,"ZCTTRUNC ",zcttrunc ,-1);
NNMivput(np,"ZCTDESC ",zctdesc ,-1);
if (!NNMispf(np,"TBADD ISPCMDS ")) return;
}
return;
}
/*********************************************************************/
static Bool
alloc_newsrc(newsrc_dsname,newsrc_ddname)
char *newsrc_dsname;
char *newsrc_ddname;
{
int space;
char *lparp;
char *rparp;
FILE *mfile;
char dsnseq [81];
char member [81];
char what_to_open [81];
space = 2;
strcpy(member,"");
strcpy(dsnseq,newsrc_dsname);
lparp = strchr(dsnseq,'(');
rparp = strchr(dsnseq,')');
if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
*lparp = '\0'; /* makes dsnseq the seq part only */
*rparp = '\0'; /* turns member into a string */
strcpy(member, lparp+1);
space = 10;
}
if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,space)) return FALSE;
/* If the data set had a member specified, it may have been
* allocated as NEW, or the member may not exist. Therefore,
* force the member to exist by opening it for output and closing
* it if it doesn't exist. Then reallocate it as an existing
* data set to prevent a B14 abend when we try to write a new
* PDS + member for output and close it.
*
* Otherwise, make sure the data set is not empty by opening it
* in append mode - this also insures that it is writable.
*/
#ifdef SASC
if (*member) {
sprintf(what_to_open, "'%s(%s)'", dsnseq, member);
/* SAS/C doesn't distinguish "member not found" from "file not
* found". He also likes to complain a lot.
* -DDI
*/
quiet(1); /* turn off stupid messages */
mfile = fopen(what_to_open,"r");
quiet(0); /* turn stupid messages back on */
if (!mfile && errno == ENFOUND) { /* Member not found */
mfile = fopen(what_to_open,"w"); /* create new member */
}
if (!mfile) {
perror(what_to_open);
return FALSE;
}
else if (fclose(mfile) < 0) {
fprintf(stderr, "Error closing %s\n", what_to_open);
return FALSE;
}
(void)NNMunalc(newsrc_ddname);
if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,0)) return FALSE;
}
else {
sprintf(what_to_open, "dd:%s", newsrc_ddname);
/* SAS/C treats an empty file as "non-existent", so we have to
* write out a blank so that NNMonrf can later open it for input
* successfully (even though nothing is there). Bizarre, huh?
* -DDI
*/
quiet(1); /* turn off stupid messages */
mfile = fopen(what_to_open,"r"); /* attempt to open for input */
quiet(0); /* turn stupid messages back on */
if (!mfile) { /* if open failed, must be empty */
mfile = fopen(what_to_open,"w");/* so open for output */
if (!mfile) { /* if that fails, give up */
perror(what_to_open);
return FALSE;
}
fputc(' ',mfile); /* make it non-empty */
}
if (fclose(mfile) < 0) { /* and close it either way */
fprintf(stderr, "Error closing %s\n", what_to_open);
return FALSE;
}
}
#else
if (*member) {
sprintf(what_to_open, "'%s(%s)'", dsnseq, member);
mfile = fopen(what_to_open,"r");
if (!mfile && errno == 104) { /* Member not found */
mfile = fopen(what_to_open,"w"); /* create new member */
}
if (!mfile) {
perror(what_to_open);
return FALSE;
}
else if (fclose(mfile) < 0) {
fprintf(stderr, "Error closing %s\n", what_to_open);
return FALSE;
}
(void)NNMunalc(newsrc_ddname);
if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,0)) return FALSE;
}
else {
sprintf(what_to_open, "dd:%s", newsrc_ddname);
mfile = fopen(what_to_open,"a");
if (!mfile) {
perror(what_to_open);
return FALSE;
}
else if (fclose(mfile) < 0) {
fprintf(stderr, "Error closing %s\n", what_to_open);
return FALSE;
}
}
#endif
return TRUE;
}
/*********************************************************************/
int
main(argc,argv)
int argc;
char **argv;
{
struct nncb *np;
char *p;
Bool (*selection_processor)();
struct hostent *client_hp;
int gethostnamerc;
int exit_return_code;
Bool display_continue;
Bool ok_to_update_newsrc;
struct nncb nn;
char newsrc_dsname [65];
exit_return_code = 0;
memset(&nn,0,sizeof(struct nncb));
np = &nn;
np->test_mode = FALSE;
np->debug_mode = FALSE;
np->batch_mode = FALSE;
np->preselection = '\0';
if (argc > 1) {
p = argv[1];
if (*p == '-') {
while (*++p) {
switch (toupper(*p)) {
case 'T': np->test_mode = TRUE; break;
case 'D': np->debug_mode = TRUE; break;
case 'B': np->batch_mode = TRUE; break;
case SELECTION_ALL:
case SELECTION_REG:
case SELECTION_NNTP:
case SELECTION_GROUP:
case SELECTION_LIST:
case SELECTION_NEWG:
case SELECTION_OPTS:
case SELECTION_EXIT:
np->preselection = *p; break;
default: fprintf(stderr,"NNMVS: Bad parameter flag %c\n", *p);
exit_return_code = 8;
}
}
}
else {
fprintf(stderr,"NNMVS: Bad parameter string %s\n",p);
exit_return_code = 8;
}
}
if (np->test_mode) __ctest(NULL);
if (np->debug_mode) {
if (!(np->debug_file = fopen("dd:nndebug","w"))) {
perror("debug file (DD NNDEBUG)");
exit_return_code = 4;
}
}
else np->debug_file = NULL;
if (np->batch_mode) {
if (!(np->batch_infile = fopen("dd:NNBATIN","r"))) {
perror("batch input file (dd:NNBATIN)");
}
if (!(np->batch_outfile = fopen("dd:NNBATOUT","w"))) {
perror("batch output file (dd:NNBATOUT)");
}
}
else {
np->batch_infile = NULL;
np->batch_outfile = NULL;
}
/* This doesn't work, and may even make things worse.
* if (signal(SIGINT,attention_handler) == SIG_ERR) {
* fprintf(stderr,"Error: unable to establish attention handler.\n");
* exit(27);
* }
*/
np->g_bytes_returned = 0;
np->g_buf_index = -1;
/* Determine the local path name. */
gethostnamerc = gethostname(np->client_hostname,MAXHOSTNAMELEN);
if (gethostnamerc < 0) {
fprintf(stderr,"NNMVS: gethostname() failed, don't know my name\n");
exit_return_code = 8;
}
else {
client_hp = gethostbyname(np->client_hostname);
if (!client_hp) {
fprintf(stderr,
"NNMVS: gethostbyname() failed, can't get my name\n");
exit_return_code = 8;
}
else {
strcpy(np->nnclient,np->client_hostname);
strcpy(np->client_hostname, client_hp->h_name);
np->client_ip_address = *(IPADDRESS *)client_hp->h_addr;
}
}
strcpy(np->nnserver,"");
np->connected_to_server = FALSE;
np->closing_connection = FALSE;
np->reconnect_in_progress = FALSE;
np->receiving_text = FALSE;
np->newsgroup_selected = FALSE;
GETMAIN(np->server_buf, char, SERVER_BUF_MSGSIZE+4,"server buffer");
GETMAIN(np->client_buf, char, CLIENT_BUF_MSGSIZE+4,"client buffer");
GETMAIN(np->nntp_command, char, CLIENT_BUF_MSGSIZE+4,"NNTP command");
if (exit_return_code > 4) /* nothing */;
else if (np->batch_mode) {
exit_return_code = NNMbatch(np);
}
else {
#ifdef FETCH
np->isplink_pointer = (int (*) ())fetch("ISPLINK");
np->ispexec_pointer = (int (*) ())fetch("ISPEXEC");
#endif
if (!NNMispf(np,"CONTROL ERRORS RETURN")) exit_return_code = 20;
else {
NNMinit(np); /* Set up command and selection code tables */
(void)NNMivput(np,"ZCMD " ,"",-1);
(void)NNMivput(np,"NNCURSOR ","",-1);
trap_ispf_command(np,"RFIND","&YRFIND"); /* enable RFIND */
NNMsopt(np,OPTION_ALL); /* Set options */
strcpy(np->newsrc_to_open,"dd:");
do {
NNMunalc(np->newsrc_to_open+3);
switch (NNMdmenu(np,&selection_processor)) { /* Display menu */
case DISPLAY_REPEAT:
case DISPLAY_ERROR: display_continue = TRUE; break;
case DISPLAY_EXIT:
case DISPLAY_FAILURE: display_continue = FALSE; break;
}
if (display_continue
&& selection_processor
&& NNMivget(np,"NNNEWSRC ",newsrc_dsname,sizeof(newsrc_dsname))
&& alloc_newsrc(newsrc_dsname,np->newsrc_to_open+3)) {
NNMclrng(np); /* Clear newsgroups */
NNMclrtx(np,NULL); /* Clear text */
NNMonrf(np,NULL); /* Open NEWSRC file */
(void)NNMivput(np,"ZCMD ","",-1); /* Clear ZCMD field */
/* Call selected function. If returns TRUE, rewrite NEWSRC */
ok_to_update_newsrc = (*selection_processor)(np);
NNMcnrf(np,NULL,
ok_to_update_newsrc); /* Close/rewrite NEWSRC file */
}
} while (display_continue && !np->quit);
exit_return_code = 0;
}
}
if (*np->maildsn) {
if (remove(np->maildsn) < 0) {
fprintf(stderr,"NNMVS: Error removing mail dataset %s\n");
}
}
if (np->connected_to_server) {
NNMdisc(np); /* disconnect from news server */
}
NNMclrng(np); /* Clear newsgroups */
FREEMAIN(np->nntp_command,"nntp command");
FREEMAIN(np->server_buf, "server buffer");
FREEMAIN(np->client_buf, "client buffer");
#define FINAL_CLOSE(A,B) \
if (A) { \
if (fclose(A) < 0) fprintf(stderr,B); \
}
FINAL_CLOSE(np->newsrc_file , "Error closing newsrc file\n");
FINAL_CLOSE(np->debug_file , "Error closing debug file\n");
FINAL_CLOSE(np->batch_infile , "Error closing batch input file\n");
FINAL_CLOSE(np->batch_outfile , "Error closing batch output file\n");
exit(exit_return_code);
}
./ ADD NAME=NNMMARR,SSI=01030019
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@MARR ")
#pragma csect(static,"NN$MARR ")
#include "nn.h"
/****** Make article read. *******************************************/
void
NNMmarr(np,gp,vp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
register VARK *vp;
{
struct newsarticle *ap;
if (IsUnread(*vp)) {
SetRead(*vp);
gp->unread_count--;
}
if (!IsNull(*vp) && !IsMissing(*vp)) {
ap = VARK2PARTICLE(*vp);
ap->action = READ;
}
return;
}
./ ADD NAME=NNMMARU,SSI=01010050
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@MARU ")
#pragma csect(static,"NN$MARU ")
#include "nn.h"
/****** Make article unread. *****************************************/
void
NNMmaru(np,gp,vp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
register VARK *vp;
{
struct newsarticle *ap;
if (IsRead(*vp)) {
SetUnread(*vp);
gp->unread_count++;
}
if (!IsNull(*vp) && !IsMissing(*vp)) {
ap = VARK2PARTICLE(*vp);
ap->action = UNREAD;
}
return;
}
./ ADD NAME=NNMNNTP,SSI=01070007
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@NNTP ")
#pragma csect(static,"NN$NNTP ")
#include "nn.h"
/****** Read server data. ********************************************/
static Bool
read_server_data(np)
Rstruc nncb *np;
{
char *lp;
NNMclrtx(np,NULL); /* Clear text */
do {
if (NNMgsrvl(np,&lp)) /* Get server line */
if (lp) {
(void)NNMouttx(np,lp,NULL); /* Output text line */
}
} while (lp);
if (np->time_to_go_home) return FALSE;
else return TRUE;
}
/************ Execute native NNTP protocol commands. *****************/
void
NNMnntp(np)
Rstruc nncb *np;
{
struct texthdr saveth;
/* np->nntp_command must contain NNTP command */
if (!np->receiving_text && !*np->nntp_command) return;
np->newsgroup_selected = FALSE; /* in case we change server's state
with a command like "GROUP xxx" */
memcpy(&saveth,&np->thdr,sizeof(struct texthdr));
memset(&np->thdr,0,sizeof(struct texthdr));
if (NNMsockt(np)) { /* Send socket command to server */
if (read_server_data(np,NULL)) { /* Read server data */
NNMvtx(np,NULL,NULL); /* View text */
}
NNMclrtx(np,NULL);
}
memcpy(&np->thdr,&saveth,sizeof(struct texthdr));
return;
}
./ ADD NAME=NNMONRF,SSI=01020041
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@ONRF ")
#pragma csect(static,"NN$ONRF ")
#include "nn.h"
/****** Open NEWSRC file. ********************************************/
void
NNMonrf(np,what_to_open)
Rstruc nncb *np;
char *what_to_open;
{
char newsrc_line[256];
char newsrc_name[GROUP_NAME_SIZE];
Rstruc newsgroup *gp;
register char *nlp;
char *temp;
int sscanf_rc;
int newsrc_registered;
int newsrc_unread;
int newsrc_topnum;
int newsrc_scan_count;
int newsrc_save_length;
if (!what_to_open) what_to_open = np->newsrc_to_open;
/* If the file does not exist, then create it. */
newsrc_scan_count = 0;
np->brand_new_newsrc = TRUE;
errno = 0;
if (!(np->newsrc_file = fopen(what_to_open,"r"))) {
if (errno == 104) { /* Member not found */
if (!(np->newsrc_file = fopen(what_to_open,"w"))) {
perror("Cannot create NEWSRC PDS member");
}
else if (fclose(np->newsrc_file) < 0) {
fprintf(stderr, "Error closing %s\n", what_to_open);
np->newsrc_file = NULL;
}
else np->newsrc_file = fopen(what_to_open,"r");
}
else perror("Cannot open NEWSRC file");
}
if (!np->newsrc_file) {
fprintf(stderr,"Severe error, NEWSRC file cannot be opened.\n");
if (!np->batch_mode) {
(void)NNMdispl(np,"NNMRCERR");
}
exit(12);
}
np->new_newsgroup_count = 0;
/* Read from the file, saving the state information. */
/********************************************************************/
/* */
/* Note: The format used here is designed to be compatible with */
/* the format used by ANU-NEWS. This is not an attempt to */
/* duplicate the "look and feel" of ANU-NEWS - it is just */
/* to be compatible with the saved state of VAX NEWS users. */
/* */
/********************************************************************/
if (feof(np->newsrc_file)) return;
/* First line: time in hex digits of last "registration", and some
* other junk. We now interpret this as the last time the status
* of the server's newsgroups was interrogated (LIST or NEWGROUPS)
* and save it.
*/
fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
if (strlen(newsrc_line) >= 13) /* if new format .newsrc file */
sscanf(newsrc_line, "%6c %6c", &np->lastNGdate, &np->lastNGtime);
if (feof(np->newsrc_file)) return;
/* The rest of the file consists of information about newsgroups.
Read until end of file or one of the special markers is found. */
fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
while (!feof(np->newsrc_file)) {
if (EQUAL(newsrc_line,"MARKLIST\n")) break;
if (EQUAL(newsrc_line,"KILLLIST\n")) break;
if (EQUAL(newsrc_line,"PROFILE\n")) break;
/* For each line, build a newsgroup entry and fill it in with
the values taken from the input line. */
/* Right now we are not checking for {classname,classname} as we
don't know how, and it would complicate things. */
nlp = strchr(newsrc_line,':');
if (!nlp) nlp = strchr(newsrc_line,'\n');
if (!nlp) {
fprintf(stderr,"Bad name in newsrc file, ignored:\n%s\n\n",
newsrc_line);
fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
continue;
}
memcpy(newsrc_name,newsrc_line,nlp-newsrc_line);
newsrc_name[nlp-newsrc_line] = '\0';
if (*nlp == '\n' || *(nlp+1) == '\n') sscanf_rc = 0;
else
sscanf_rc = sscanf(nlp,": (%d) [%d,%d] %n",
&newsrc_registered,
&newsrc_unread,
&newsrc_topnum,
&newsrc_scan_count);
switch (sscanf_rc) { /* Note use of switch WITHOUT break here. */
case EOF: newsrc_registered = 1;
case 0: newsrc_registered = 1;
case 1: newsrc_unread = 0;
case 2: newsrc_topnum = 0;
nlp = NULL;
case 3: break;
default: break;
}
np->brand_new_newsrc = FALSE;
/* Allocate a newsgroup for this record. */
gp = NNMaddng(np,newsrc_name); /* Add newsgroup */
if (!gp) {
fprintf(stderr,"Cannot initialize newsgroup: %s\n",newsrc_name);
fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
continue;
}
/* Now, collect the information on what articles were read. */
SetGroupFromNewsrc(gp);
gp->low_number = 1; /* or new field from newsrc? */
gp->high_number = newsrc_topnum;
gp->vector_first = 0;
gp->vector_last = 0;
gp->article_count = gp->high_number - gp->low_number + 1;
gp->unread_count = newsrc_unread;
gp->registered = newsrc_registered;
if (gp->registered == -1) {
SetNewGroup(gp);
gp->registered = 0;
np->new_newsgroup_count++;
}
/* At this early point, we just save the NEWSRC line and
* create the article vector later, when we really need it.
*/
if (!nlp) {
fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
continue;
}
nlp += newsrc_scan_count;
/* Save the newsrc data (following the [unread,topnum] spec) */
if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
FREEMAIN(gp->saved_newsrc_line,"stale saved newsrc line");
}
if (*nlp == '\0') nlp = "\n";
newsrc_save_length = strlen(nlp) + 1;
if (newsrc_save_length <= sizeof(gp->saved_newsrc_data)) {
gp->saved_newsrc_line = gp->saved_newsrc_data;
}
else {
GETMAIN(gp->saved_newsrc_line,char,newsrc_save_length,
"saved newsrc line");
if (!gp->saved_newsrc_line) {
fprintf(stderr,"Cannot save newsrc line for %s, terminating.\n",
newsrc_name);
return;
}
}
strcpy(gp->saved_newsrc_line,nlp);
for (;;) {
fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
if (feof(np->newsrc_file)) break;
if (newsrc_line[0] != ' ') break;
nlp = newsrc_line;
GETMAIN(temp,char,strlen(gp->saved_newsrc_line)+strlen(nlp)+1,
"saved newsrc line continuation");
if (!temp) {
fprintf(stderr,"Cannot save newsrc line for %s, terminating.\n",
newsrc_name);
return;
}
strcpy(temp,gp->saved_newsrc_line); /* should include newline */
strcat(temp,nlp);
if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
FREEMAIN(gp->saved_newsrc_line,"old saved newsrc line");
}
gp->saved_newsrc_line = temp;
} /* end for - at this point we have no more newsrc continuations */
} /* end while */
/* At this point we have finished reading newsrc.
Ignore everything once MARKLIST, KILLLIST, or PROFILE is seen.
We don't handle any of that stuff. */
return;
}
./ ADD NAME=NNMOUTTX,SSI=01020023
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@OUTTX")
#pragma csect(static,"NN$OUTTX")
#include "nn.h"
/****** Output a line of text retrieved from the server. *************/
struct textline *
NNMouttx(np,line,ap)
Rstruc nncb *np;
char *line;
Rstruc newsarticle *ap;
{
struct texthdr *thp;
struct textline *tp;
short line_length;
short total_text_length;
short tab_expansion_length;
Bool tabs_present;
char *p;
char *q;
char *t;
int e;
int u;
static char tab_expansion_buffer[8*TEXT_BYTES];
/* If article is not specified, use main nncb, else article's text */
thp = (ap ? &ap->thdr : &np->thdr);
/* If line starts with double period, make it a single period. */
if (ap && memcmp(line,"..",2) == 0) line++;
/* Add this line to the current queue of server text lines. */
/* First, expand tabs in the line. */
line_length = strlen(line);
t = strchr(line,'\t');
if (!t) {
tabs_present = FALSE;
total_text_length = line_length + 1;
}
else { /* expand tabs */
tabs_present = TRUE;
p = line;
q = line + line_length;
e = 0;
memset(tab_expansion_buffer,' ',sizeof(tab_expansion_buffer));
for (;;) {
u = t - p;
if (u > 0) {
memcpy(tab_expansion_buffer+e,p,u);
e += u;
}
if (t == q) break;
e = e / 8 * 8 + 8;
p = t+1;
t = strchr(p,'\t');
if (!t) t = q;
}
tab_expansion_length = e;
tab_expansion_buffer[tab_expansion_length] = '\0';
total_text_length = line_length + tab_expansion_length + 1;
}
GETMAIN(tp, char, offsetof(struct textline, text) + total_text_length,
"text line");
if (!tp) {
ERR1("There is not enough virtual storage to process server text.");
return NULL;
}
tp->next = NULL;
tp->text_length = line_length;
strcpy(tp->text,line);
if (tabs_present) {
tp->tab_expanded_text_length = tab_expansion_length;
tp->tab_expanded_text = tp->text + line_length;
strcpy(tp->tab_expanded_text,tab_expansion_buffer);
}
else {
tp->tab_expanded_text_length = line_length;
tp->tab_expanded_text = tp->text;
}
if (!thp->last_text_line) {
thp->first_text_line = tp;
thp->text_body_line = tp;
thp->current_text_line = tp;
}
else thp->last_text_line->next = tp;
thp->last_text_line = tp;
thp->text_line_count++;
if (thp->text_max_length < tp->text_length)
thp->text_max_length = tp->text_length;
if (thp->text_max_tab_expanded_length < tp->tab_expanded_text_length)
thp->text_max_tab_expanded_length = tp->tab_expanded_text_length;
return tp;
}
./ ADD NAME=NNMPICK,SSI=01040058
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@PICK ")
#pragma csect(static,"NN$PICK ")
#include "nn.h"
/****** Collect text. ************************************************/
static void
collect_text(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
char *lp;
np->sending_text = TRUE;
for (;;) {
if (!NNMgsrvl(np,&lp)) break; /* Get server line */
if (lp == NULL) break;
if (strcmp(lp,".") == 0) break;
if (!NNMouttx(np,lp,ap)) break; /* Output text line */
}
return;
}
/****** Maybe suppress header line. **********************************/
static void
maybe_suppress_header_line(np,ap,tp,header_name)
Rstruc nncb *np;
Rstruc newsarticle *ap;
Rstruc textline *tp;
char *header_name;
{
char temphdr[INTERNET_SIZE+2];
Bool suppress;
switch (np->nnrfcopt[0]) {
case '\0':
case 'A': /* show all RFC822 headers */
suppress = FALSE;
break;
case 'B': /* show all except those in exclude list */
sprintf(temphdr," %s ",header_name);
if (strstr(np->nnrfcexc,temphdr)) suppress = TRUE;
else suppress = FALSE;
break;
case 'C': /* show only those in include list */
sprintf(temphdr," %s ",header_name);
if (strstr(np->nnrfcinc,temphdr)) suppress = FALSE;
else suppress = TRUE;
break;
case 'D': /* show none */
suppress = TRUE;
break;
}
if (suppress) {
if (tp->text_length >= 0) {
tp->text_length |= 0x8000; /* force sign bit negative */
ap->thdr.text_line_count--;
}
}
else {
if (tp->text_length < 0) {
tp->text_length &= 0x7fff; /* force sign bit positive */
ap->thdr.text_line_count++;
}
}
return;
}
/****** Apply header suppression. ***********************************/
static void
apply_header_suppression(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
struct textline *tp;
struct texthdr *thp;
char *cp;
char *colonp;
int header_index;
char header_name[INTERNET_SIZE];
thp = &ap->thdr;
strcpy(header_name,"");
for (tp=thp->first_text_line; tp; tp=tp->next) {
if (tp->text[0] == '\0') break;
if (tp->text[0] == ' ' ||
tp->text[0] == '\t') {
cp = tp->text + strspn(tp->text," \t");
if (*cp == '\0') break;
}
else {
header_index = 0;
colonp = strchr(tp->text,':');
if (!colonp) break;
strcpy(header_name,"");
for (cp = tp->text;cp<colonp;cp++) {
header_name[header_index++] = toupper(*cp);
}
header_name[header_index] = '\0';
}
if (*header_name) {
maybe_suppress_header_line(np,ap,tp,header_name);
}
}
thp->text_body_line = tp;
return;
}
/****** Pick article before processing. ******************************/
Bool
NNMpick(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
Rstruc newsgroup *gp;
char *lp;
char bad_status = ERROR;
Bool retval = TRUE;
Bool retrieve_header = FALSE;
Bool retrieve_body = FALSE;
np->another_article = NULL_ARTICLE_COOKIE;
gp = np->current_newsgroup;
if (!gp) {
CRIT1("No current newsgroup. This should never happen.");
return FALSE;
}
if (ap == V_NULL_ARTICLE) {
ERR1("This article does not exist - how could it be chosen?");
return FALSE;
}
if (ap == V_MISSING_ARTICLE) {
ERR1("This article is missing - how could it be chosen?");
return FALSE;
}
if (NoSuchArticle(ap)) {
ERR4("Article %d of %s does not exist in server %s.",
ap->number, gp->name, np->nnserver);
retval = FALSE;
}
else if (ArticleAbsent(ap)) {
ERR4("Article %d of %s was not retrieved by server %s.",
ap->number, gp->name, np->nnserver);
retval = FALSE;
}
else if (ArticleError(ap)) {
ERR4("Error getting article %d of %s from server %s.",
ap->number, gp->name, np->nnserver);
retval = FALSE;
}
else {
retrieve_header = !ArticleHeadRetrieved(ap);
retrieve_body = !ArticleBodyRetrieved(ap);
}
if (retrieve_header || retrieve_body) {
if (!NNMestng(np,NULL)) { /* Establish newsgroup */
SetGroupError(gp);
OffGroupSelected(gp);
return FALSE;
}
if (retrieve_header) {
if (!NNMrarh(np,gp,NULL,ap->number,NULL)) {
ERR4("Article %d of %s could not be retrieved from server %s.",
ap->number, gp->name, np->nnserver);
ap->action = MISSING;
return FALSE;
}
}
sprintf(np->nntp_command,"BODY %d",ap->number);
if (!NNMsockt(np)) return FALSE; /* Send socket cmd to server*/
if (!NNMgsrvl(np,&lp)) return FALSE; /* Get server line */
switch(np->nntp_message_num) {
case 220: /* article retrieved - head and body follow */
break;
case 221: /* article retrieved - head follows */
break;
case 222: /* article retrieved - body follows */
break;
case 423: /* no such article number in this group */
ERR4("Article %d of %s is missing from server %s.",
ap->number, gp->name, np->nnserver);
bad_status = MISSING;
retval = FALSE;
break;
case 430: /* no such article found */
ERR4("Article %d of %s could not be found by server %s.",
ap->number, gp->name, np->nnserver);
bad_status = MISSING;
retval = FALSE;
break;
case 223: /* article retrieved - request text separately */
case 412: /* no newsgroup has been selected */
case 420: /* no current article has been selected */
default: NNMrperr(np); /* Report protocol error */
retval = FALSE;
break;
}
}
if (retval == FALSE) {
ap->action = bad_status;
return FALSE;
}
SetArticleRetrieved(ap);
ap->action = NO_ACTION;
if (retrieve_body) {
if (!NNMouttx(np," ",ap)) return FALSE; /* output text line */
collect_text(np,ap);
}
apply_header_suppression(np,ap);
return TRUE;
}
./ ADD NAME=NNMPMSG,SSI=01040049
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#define SUPPRESS_V_DECLARATION
#pragma csect(code, "NN@PMSG ")
#pragma csect(static,"NN$PMSG ")
#include "nn.h"
/****** Set an ISPF message, or write to SYSOUT if batch mode. *******/
void
NNMpmsg(np,msgtype,msghelp,msgformat) /* also ... for sprintf args */
Rstruc nncb *np;
int msgtype;
char *msghelp;
char *msgformat;
{
va_list argp;
char *cp;
char zerrsm [25];
char zerrhm [9];
char zerralrm [4];
char zerrlm [ZERRLM_SIZE];
char buf [257];
va_start(argp,msgformat);
vsprintf(buf,msgformat,argp);
va_end(argp);
cp = strchr(buf,';');
if (cp) {
*cp = '\0';
strncpy(zerrsm,buf, sizeof(zerrsm));
strncpy(zerrlm,cp+1,sizeof(zerrlm));
}
else {
strcpy(zerrsm,"");
strncpy(zerrlm,buf,sizeof(zerrlm));
}
zerrsm[sizeof(zerrsm)-1] = '\0';
zerrlm[sizeof(zerrlm)-1] = '\0';
if (msghelp) strcpy(zerrhm, msghelp);
else strcpy(zerrhm, "*" );
if (np->batch_mode) {
if (!*zerrsm) {
switch (msgtype) {
case NOTIFY_MSG: strcpy(zerrsm,"Note"); break;
case WARNING_MSG:
case CRITICAL_MSG:
default: strcpy(zerrsm,"Error"); break;
}
}
fprintf(np->batch_outfile,"%s: %s\n", zerrsm, zerrlm);
return;
}
switch (msgtype) {
case NOTIFY_MSG: strcpy(zerralrm,"NO "); break;
case WARNING_MSG:
case CRITICAL_MSG:
default: strcpy(zerralrm,"YES"); break;
}
(void)NNMivput(np,"ZERRSM ", zerrsm, -1);
(void)NNMivput(np,"ZERRLM ", zerrlm, -1);
(void)NNMivput(np,"ZERRHM ", zerrhm, -1);
(void)NNMivput(np,"ZERRALRM ",zerralrm, -1);
np->setmsg = TRUE;
return;
}
./ ADD NAME=NNMPNG,SSI=010D0051
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@PNG ")
#pragma csect(static,"NN$PNG ")
#include "nn.h"
/****** Set articles missing based on XHDR info. *********************/
static void
set_articles_missing(np,gp,anum,xnum)
Rstruc nncb *np;
Rstruc newsgroup *gp;
int anum;
int xnum;
{
VARK *vp;
while (anum < xnum) {
if (np->debug_file) {
fprintf(np->debug_file, "Setting article %d missing\n",anum);
}
vp = &GETVARK(gp,anum);
if (IsUnread(*vp)) gp->unread_count--;
SetMissingRead(*vp);
anum++;
}
return;
}
/****** Do XHDR stuff for newsgroup. *********************************/
static void
do_xhdr(np,gp,allp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Bool allp;
{
char *lp;
char *xhdr_subject;
VARK *vplow;
VARK *vphigh;
VARK *vpfirst;
VARK *vplast;
int range;
int xhdr_article_number;
int scan_count;
int xhdr_low;
int xhdr_high;
int anum;
/* If we need to know about missing articles,
* we try to determine it via XHDR.
*
* We don't do anything useful with the headers yet. We should.
* That requires doing something with the allocation of the
* newsarticle structures.
*
* We use XHDR when:
*
* (1) the total article count is less than the difference between
* the low and high count from the GROUP command
*
* (2) there are null (never-retrieved) articles
*
* Fine, but requires looping around the article vector.
* Now, if we only want unread articles, we don't want to XHDR
* the whole thing, so in that case we only do this if there are
* any null-and-unread articles.
*
* *** this is still no good because articles are set missing
* *** but cannot be set present if we don't know if they will
* *** be eligible or not. I will HAVE to keep the subject and
* *** set the article pointer to a placeholder with the subject,
* *** which means more article structures allocated, but that is
* *** probably the best thing to do.
*
* Solution: we call this routine only when a group migrates
* from unselected to selected status - either when it goes
* from never-selected to selected-unread, from never-selected
* to selected-all, or from selected-unread to selected-all.
* The first of the above cases is where allp is set to false
* so that we don't XHDR the whole thing just for a few unread items.
*
*/
if (!gp->article_vector) return;
if (np->xhdr_not_available) return;
range = gp->vector_last - gp->vector_first + 1;
if (range <= gp->article_count) return;
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
if (allp) {
for (vplow = vpfirst; vplow <= vplast; vplow++) {
if (IsNull(*vplow)) break;
}
if (vplow > vplast) return; /* if no null articles */
for (vphigh = vplast; vphigh > vplow; vphigh--) {
if (IsNull(*vphigh)) break;
}
}
else {
for (vplow = vpfirst; vplow <= vplast; vplow++) {
if (IsNull(*vplow) && IsUnread(*vplow)) break;
}
if (vplow > vplast) return; /* if no null articles */
for (vphigh = vplast; vphigh > vplow; vphigh--) {
if (IsNull(*vphigh) && IsUnread(*vphigh)) break;
}
}
xhdr_low = VARK2NUMBER(gp,vplow);
xhdr_high = VARK2NUMBER(gp,vphigh);
/* Send "XHDR SUBJECT nnn-nnn" to news server. */
NNMestng(np,NULL); /* set server "GROUP" if necessary */
/* e.g. going from unread-only to all */
sprintf(np->nntp_command,"XHDR SUBJECT %d-%d",xhdr_low,xhdr_high);
if (!NNMsockt(np)) return; /* Send socket command to server */
if (!NNMgsrvl(np,&lp)) return; /* Get server line */
switch (np->nntp_message_num) {
case 221: /* subject fields follow */
np->xhdr_not_available = FALSE;
break;
case 500: /* command unrecognized */
np->xhdr_not_available = TRUE;
break;
default:
NNMrperr(np); /* Report protocol error */
return;
}
if (np->xhdr_not_available) return;
/* assert np->sending_text == TRUE; */
anum = xhdr_low;
for (;;) {
if (!NNMgsrvl(np,&lp)) return; /* Get server line */
if (lp == NULL) break;
if (strcmp(lp,".") == 0) break;
if (1 != sscanf(np->nntp_message_text, "%d %n",
&xhdr_article_number, &scan_count)) {
NNMrbfm(np); /* Report bad format message */
return;
}
xhdr_subject = np->nntp_message_text + scan_count;
if (np->debug_file) {
fprintf(np->debug_file,"XHDR: article='%d', subject='%s'\n",
xhdr_article_number, xhdr_subject);
}
set_articles_missing(np,gp,anum,xhdr_article_number);
anum = xhdr_article_number + 1;
}
set_articles_missing(np,gp,anum,xhdr_high);
return;
}
/****** Pick newsgroup. **********************************************/
Bool
NNMpng(np,gp,do_titles,do_sort)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Fool do_titles;
Fool do_sort;
{
Rstruc newsgroup *gp1;
Bool result = TRUE;
Bool was_selected_unread;
Bool was_selected_read;
np->current_newsgroup = gp;
np->newsgroup_selected = FALSE;
np->newsgroup_not_found = FALSE;
was_selected_read = GroupSelectedRead(gp);
was_selected_unread = GroupSelectedUnread(gp);
if (!np->batch_mode) {
(void)NNMivput(np,"NNGROUP ",gp->name,-1);
}
if (GroupSelected(gp)) {
if (np->show_all_articles) {
SetGroupSelectedRead(gp);
}
gp1 = gp;
}
else {
gp1 = NNMdng(np,gp,NULL); /* do newsgroup by address */
}
if (!gp1) {
result = FALSE;
}
else if (np->newsgroup_not_found) {
SetNoSuchGroup(gp);
gp->article_count = 0;
gp->unread_count = 0;
result = FALSE;
}
else {
gp = gp1;;
if (!was_selected_read && GroupSelectedRead(gp)) {
do_xhdr(np,gp,TRUE); /* do XHDR stuff for all */
}
else if (!was_selected_unread && GroupSelectedUnread(gp)) {
do_xhdr(np,gp,FALSE); /* do XHDR stuff for unread */
}
if (do_titles) (void)NNMrart(np,gp,FALSE,TRUE);
if (do_sort) (void)NNMsort(np,gp);
result = NNMvar(np,gp); /* View articles */
}
np->current_newsgroup = NULL;
np->newsgroup_selected = FALSE;
/* hack to position newsgroup display*/
strcpy(np->nngroup, gp->name);
return result;
}
./ ADD NAME=NNMQAR,SSI=01050011
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@QAR ")
#pragma csect(static,"NN$QAR ")
#include "nn.h"
#define OUT1(A) (void)NNMouttx(np,(A),NULL)
#define OUT2(A,B) sprintf(temp,(A),(B)), OUT1(temp)
#define OUT3(A,B,C) sprintf(temp,(A),(B),(C)), OUT1(temp)
#define ADD1(A) strcat(stat,(A))
#define ADD2(A,B) sprintf(temp,(A),(B)), ADD1(temp)
/****** Query article. ***********************************************/
Bool
NNMqar(np,ap)
Rstruc nncb *np;
Rstruc newsarticle *ap;
{
Rstruc newsgroup *gp;
char stat[129];
char temp[129];
gp = np->current_newsgroup;
if (!gp) {
CRIT1("No current newsgroup. This should never happen.");
return FALSE;
}
NNMclrtx(np,NULL);
if (ap == V_NULL_ARTICLE) {
OUT1("Null article");
}
else if (ap == V_MISSING_ARTICLE) {
OUT1("Missing article");
}
else {
OUT1("");
OUT3(" Struct at %8.8X: Article %d", ap, ap->number);
OUT1("");
OUT2("status.........................%2.2X", ap->status);
if (NoSuchArticle(ap)) OUT1(" NoSuchArticle" );
if (ArticleAbsent(ap)) OUT1(" ArticleAbsent" );
if (ArticleError(ap)) OUT1(" ArticleError" );
if (ArticleBadData(ap)) OUT1(" ArticleBadData" );
if (ArticleHeadRetrieved(ap)) OUT1(" ArticleHeadRetrieved" );
if (ArticleBodyRetrieved(ap)) OUT1(" ArticleBodyRetrieved" );
strcpy(stat,"action.........................");
switch (ap->action) {
case NO_ACTION: ADD1("NO_ACTION"); break;
case READ: ADD1("READ"); break;
case RETRIEVED: ADD1("RETRIEVED"); break;
case EXTRACTED: ADD1("EXTRACTED"); break;
case PRINTED: ADD1("PRINTED"); break;
case UNREAD: ADD1("UNREAD"); break;
case MISSING: ADD1("MISSING"); break;
case ERROR: ADD1("ERROR"); break;
case CANCELLED: ADD1("CANCELLED"); break;
default: ADD2("%d",ap->action); break;
}
OUT1(stat);
OUT2("number.........................%d", ap->number);
OUT2("from...........................%s", ap->from);
OUT2("subject........................%s", ap->subject);
OUT2("date...........................%s", ap->date);
OUT2("message_id.....................%s", ap->message_id);
if (ap->csubject)
OUT2("csubject.......................%s", ap->csubject);
else
OUT1("csubject is NULL");
OUT2("text line count................%d", ap->thdr.text_line_count);
OUT2("text max length................%d", ap->thdr.text_max_length);
OUT2("text max tab expanded length...%d",
ap->thdr.text_max_tab_expanded_length);
OUT2("text body line..............%8.8X",ap->thdr.text_body_line);
OUT2("first text line.............%8.8X",ap->thdr.first_text_line);
OUT2("current text line...........%8.8X",ap->thdr.current_text_line);
OUT2("last text line..............%8.8X",ap->thdr.last_text_line);
}
NNMvtx(np,NULL,NULL);
return TRUE;
}
./ ADD NAME=NNMQNG,SSI=01100058
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@QNG ")
#pragma csect(static,"NN$QNG ")
#include "nn.h"
#define OUT1(A) (void)NNMouttx(np,(A),NULL)
#define OUT2(A,B) sprintf(temp,(A),(B)), OUT1(temp)
#define OUT3(A,B,C) sprintf(temp,(A),(B),(C)), OUT1(temp)
#define ADD1(A) strcat(stat,(A))
#define ADD2(A,B) sprintf(temp,(A),(B)), ADD1(temp)
/****** Query newsgroup. *********************************************/
void
NNMqng(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
struct newsarticle *ap;
int i;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
VARK **wp;
VARK **wpfirst;
VARK **wplast;
char stat[129];
char temp[129];
if (!gp) return;
NNMclrtx(np,NULL);
OUT1("");
OUT3(" Struct at %8.8X: Newsgroup '%s'", gp, gp->name);
OUT1("");
OUT2("next.......................%8.8X", gp->next);
OUT2("next2......................%8.8X", gp->next2);
OUT2("next3......................%8.8X", gp->next3);
OUT2("saved_newsrc_line..........%8.8X", gp->saved_newsrc_line);
OUT2("article_vector.............%8.8X", gp->article_vector);
OUT2("sort_vector................%8.8X", gp->sort_vector);
OUT2("low_number.................%d", gp->low_number);
OUT2("high_number................%d", gp->high_number);
OUT2("vector_first...............%d", gp->vector_first);
OUT2("vector_last................%d", gp->vector_last);
OUT2("article_count..............%d", gp->article_count);
OUT2("unread_count...............%d", gp->unread_count);
OUT2("sort_count.................%d", gp->sort_count);
OUT2("article_vector_len.........%d", gp->article_vector_len);
OUT2("registered.................%d", gp->registered);
OUT2("saved_newsrc_data..........%s", gp->saved_newsrc_data);
OUT2("status.....................%2.2X", gp->status);
if (NoSuchGroup(gp)) OUT1(" NoSuchGroup" );
if (NewGroup(gp)) OUT1(" NewGroup" );
if (GroupFromNewsrc(gp)) OUT1(" GroupFromNewsrc" );
if (GroupListed(gp)) OUT1(" GroupListed" );
if (GroupSelectedUnread(gp)) OUT1(" GroupSelectedUnread" );
if (GroupSelectedRead(gp)) OUT1(" GroupSelectedRead" );
if (GroupError(gp)) OUT1(" GroupError" );
if (GroupInTable(gp)) OUT1(" GroupInTable" );
OUT2("name.......................%s", gp->name);
if (gp->saved_newsrc_line) {
OUT1("");
OUT1("Saved newsrc line follows:");
OUT1("");
OUT1(gp->saved_newsrc_line);
OUT1("");
OUT1("");
}
if (gp->article_vector) {
OUT1("");
OUT1("Article vector follows:");
OUT1("");
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst, i = gp->vector_first; vp <= vplast; vp++,i++) {
sprintf(stat," %10d: %8.8X ",i,*vp);
ap = VARK2PARTICLE(*vp);
if (ap == V_NULL_ARTICLE) ADD1("Null ");
else if (ap == V_MISSING_ARTICLE) ADD1("Missing ");
else ADD2("%8.8X ",ap);
if (IsKnown(*vp)) ADD1("Known ");
else ADD1("Unknown ");
if (IsEligible(*vp)) ADD1("Eligible ");
else ADD1("Ineligible ");
if (IsRead(*vp)) ADD1("Read ");
else ADD1("Unread ");
OUT1(stat);
}
}
if (gp->sort_vector) {
OUT1("");
OUT1("Sort vector follows:");
OUT1("");
wpfirst = gp->sort_vector;
wplast = gp->sort_vector + gp->sort_count;
for (wp = wpfirst; wp < wplast; wp++) {
OUT3(" %8.8X: %8.8X",*wp,**wp);
}
}
NNMvtx(np,NULL,NULL);
return;
}
./ ADD NAME=NNMRARH,SSI=010B0033
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@RARH ")
#pragma csect(static,"NN$RARH ")
#include "nn.h"
/****** Get article. *************************************************/
static struct newsarticle *
get_article(np,gp,vp,anum,cdp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
VARK *vp;
int anum;
struct countdown *cdp;
{
struct newsarticle *ap;
char *lp;
char *cp;
struct textline *tp;
int header_index;
char header_name[INTERNET_SIZE];
if (anum <= 0) anum = VARK2NUMBER(gp,vp);
SetUnknown(*vp);
/* Allocate a struct newsarticle for this article */
GETMAIN(ap, struct newsarticle, 1, "news article");
if (!ap) {
ERR2("There is not enough memory to retrieve article %d.", anum);
SetIneligible(*vp);
return NULL;
}
*vp = ((VARK)ap | VARK2BITS(*vp));
memset(ap,0,sizeof(struct newsarticle));
ClearArticleStatus(ap);
ap->action = ERROR;
ap->number = anum;
if (!NNMestng(np,NULL)) { /* Establish newsgroup */
SetArticleError(ap);
SetIneligible(*vp);
return NULL;
}
tp = NULL;
/* If user asked for screen updates, do them here. */
NNMupdt(np,cdp,"NNMLART2");
/* Ask for the head of the article by number. */
/* (Is it better to ask by message-id? Dunno) */
sprintf(np->nntp_command,"HEAD %d",ap->number);
if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
if (NNMgsrvl(np,&lp)) { /* Get server line */
switch (np->nntp_message_num) {
case 221: /* article retrieved, head follows */
SetArticleHeadRetrieved(ap);
break;
case 423: /* no such article number in this group */
SetNoSuchArticle(ap);
ap->action = MISSING;
break;
case 430: /* no such article found */
SetArticleAbsent(ap);
ap->action = MISSING;
break;
default:
SetArticleError(ap);
NNMrperr(np); /* Report protocol error */
break;
}
}
if (!ArticleHeadRetrieved(ap)) {
if IsUnread(*vp) gp->unread_count--;
SetMissingRead(*vp);
return NULL;
}
/* Scan the text for headers and extract the subject and whatever. */
ap->subject = "";
ap->from = "";
ap->message_id = "";
ap->date = "";
np->sending_text = TRUE; /* Stuff following is header text */
for (;;) {
if (!NNMgsrvl(np,&lp)) break; /* Get server line */
if (lp == NULL) break;
if (np->server_finished_replying) break;
if (!(tp=NNMouttx(np,lp,ap))) break; /* Output text line */
if (*(cp=tp->tab_expanded_text) == ' ') continue;
header_name[0] = '\0';
header_index = 0;
while (*cp != ':') {
if (*cp == '\0' || *cp == ' ') {
NNMdump(np,"Warning, bad header line",lp,strlen(lp));
SetArticleBadData(ap);
break;
}
else header_name[header_index++] = toupper(*cp++);
}
header_name[header_index] = '\0';
cp = skip_whitespace(cp+1);
if (EQUAL(header_name,"FROM")) {
ap->from = cp;
}
else if (EQUAL(header_name,"SUBJECT")) {
ap->subject = cp;
}
else if (EQUAL(header_name,"MESSAGE-ID")) {
ap->message_id = cp;
}
else if (EQUAL(header_name,"DATE")) {
cp = strpbrk(cp,"0123456789");
if (!cp) cp = "*BAD DATE*";
ap->date = cp;
}
}
/* Prepare ISPF variables for possible panel or message processing. */
if (!np->batch_mode) {
(void)NNMivput(np,"NNTSUBJ " ,ap->subject,-1);
}
/* Since we retrieved the article, it can't be missing, can it? */
SetKnown(*vp);
ap->action = NO_ACTION;
return ap;
}
/****** Retrieve article header. *************************************/
struct newsarticle *
NNMrarh(np,gp,vp,anum,cdp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
VARK *vp;
int anum;
struct countdown *cdp;
{
Rstruc newsarticle *ap;
/* Note that either vp or anum may be null (zero), but NOT BOTH. */
if (!vp) vp = &GETVARK(gp,anum);
ap = VARK2PARTICLE(*vp);
if (ap == V_NULL_ARTICLE) return get_article(np,gp,vp,anum,cdp);
else if (ap == V_MISSING_ARTICLE) return NULL;
else return ap;
}
./ ADD NAME=NNMRART,SSI=010C0036
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@RART ")
#pragma csect(static,"NN$RART ")
#include "nn.h"
/****** Retrieve all article titles. *********************************/
int
NNMrart(np,gp,not_just_unread,not_just_only)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Fool not_just_unread;
Fool not_just_only;
{
struct newsarticle *ap;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
VARK **wp;
VARK **wpfirst;
VARK **wplast;
int count;
struct countdown cd;
Bool save_show_all_articles;
char save_article_only_char;
np->bypass_header_retrieval = FALSE;
if (!gp->article_vector) return 0;
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
if (np->updatefreq < 0) {
cd.do_update = FALSE;
cd.done = 0;
cd.to_do = 0;
}
else {
cd.do_update = TRUE;
cd.done = 0;
cd.to_do = 0;
if (not_just_unread) {
for (vp = vpfirst; vp <= vplast; vp++) {
if (IsNull(*vp)) cd.to_do++;
}
}
else {
for (vp = vpfirst; vp <= vplast; vp++) {
if (IsNull(*vp) && IsUnread(*vp)) cd.to_do++;
}
}
}
if (not_just_unread) {
save_show_all_articles = np->show_all_articles;
np->show_all_articles = TRUE;
}
if (not_just_only) {
save_article_only_char = np->article_only_string[0];
np->article_only_string[0] = '\0';
}
count = 0;
if (gp->sort_vector) {
wpfirst = gp->sort_vector;
wplast = gp->sort_vector + gp->sort_count - 1;
for (wp = wpfirst; wp <= wplast; wp++) {
SetUnknown(**wp);
if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) { /* Choose article */
count++;
}
}
}
else {
for (vp = vpfirst; vp <= vplast; vp++) {
SetUnknown(*vp);
if (NNMcar(np,gp,0,vp,NULL,&cd,RETRIEVE)) { /* Choose article */
count++;
}
}
}
/*
* IMPORTANT: On return, articles are set eligible if their titles
* have been retrieved, even if we fudged the criteria. We could
* reset them all to unknown, but NNMsort needs this information,
* so it is the responsibility of the caller of NNMrart to reset
* all the statuses if it called NNMrart with fudging turned on.
*/
if (not_just_unread) {
np->show_all_articles = save_show_all_articles;
}
if (not_just_only) {
np->article_only_string[0] = save_article_only_char;
}
return count; /* number of eligible and retrieved, for NNMsort */
}
./ ADD NAME=NNMRBFM,SSI=01000057
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@RBFM ")
#pragma csect(static,"NN$RBFM ")
#include "nn.h"
/****** Report bad format message. ***********************************/
void
NNMrbfm(np)
Rstruc nncb *np;
{
NNMclrtx(np,NULL); /* Clear text */
CRIT2("NNTP message from server %s has invalid format.", np->nnserver);
(void)NNMouttx(np,np->server_buf,NULL); /* Output text line */
NNMvtx(np,NULL,NULL); /* View text */
return;
}
./ ADD NAME=NNMRECON,SSI=01030026
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@RECON")
#pragma csect(static,"NN$RECON")
#include "nn.h"
/****** Reconnect to server. *****************************************/
Bool
NNMrecon(np)
Rstruc nncb *np;
{
struct newsgroup *gp;
char save_command[CLIENT_BUF_MSGSIZE+4];
if (np->dont_reconnect) {
CRIT2(
"Disconnected from server %s. Reconnection will not be attempted.",
np->nnserver);
return FALSE;
}
np->connected_to_server = FALSE;
np->reconnect_in_progress = TRUE;
if (!np->batch_mode) {
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLRCON)");
}
/*
* fprintf(stderr,"Lost connection, possible timeout.\n");
* fprintf(stderr,"Attempting reconnection to news server %s (%s)\n",
* np->server_hostname,
* np->server_ip_addrstr);
*/
if (!NNMconn(np)) { /* Connect to news server */
CRIT2("Reconnection failed to server %s after disconnect.",
np->nnserver);
return FALSE;
}
/* If there is a current newsgroup and we're not currently trying
* to issue a "GROUP" command, then reestablish server's state.
*/
if ((gp=np->current_newsgroup)
&& memcmp(np->nntp_command,"GROUP ",6)) /* not "GROUP" */ {
if (!np->batch_mode) {
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
(void)NNMispf(np,"DISPLAY PANEL(NNMLRSNG)");
}
strcpy(save_command,np->nntp_command);
/* Establish newsgroup */
if (!NNMestng(np,gp->name)) {
strcpy(np->nntp_command,save_command);
CRIT3(
"Reselect of newsgroup %s failed during reconnection to %s.",
gp->name, np->nnserver);
return FALSE;
}
strcpy(np->nntp_command,save_command);
}
np->reconnect_in_progress = FALSE;
return TRUE;
}
./ ADD NAME=NNMRPERR,SSI=01000026
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@RPERR")
#pragma csect(static,"NN$RPERR")
#include "nn.h"
/****** Report protocol error. ***************************************/
void
NNMrperr(np)
Rstruc nncb *np;
{
NNMclrtx(np,NULL); /* Clear text */
CRIT2("NNTP protocol error. Unexpected response by server %s.",
np->nnserver);
(void)NNMouttx(np,np->server_buf,NULL); /* Output text line */
NNMvtx(np,NULL,NULL); /* View text */
return;
}
./ ADD NAME=NNMSAVE,SSI=01000057
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@SAVE ")
#pragma csect(static,"NN$SAVE ")
#include "nn.h"
#include "nnbatch.h"
/****** Save NEWSRC file. ********************************************/
Bool
NNMsave(np,rest)
Rstruc nncb *np;
char *rest;
{
Rstruc batch *bp;
if (np->batch_mode) {
bp = np->batch_hook;
if (GETB("CHECKPOINT") == FALSE) return TRUE;
}
NNMcnrf(np,NULL,TRUE); /* Close NEWSRC file */
/* Reopen the file for input. Don't let anybody else sneak in. */
if (!(np->newsrc_file = fopen(np->newsrc_to_open,"r"))) {
perror("Cannot reopen NEWSRC file");
}
return TRUE;
}
./ ADD NAME=NNMSOCKT,SSI=01030031
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@SOCKT")
#pragma csect(static,"NN$SOCKT")
#include "nn.h"
/****** Output one data line for the server. *************************/
Bool
NNMsockt(np)
Rstruc nncb *np;
{
int nntp_bytes;
int writrc;
char *s_buf;
nntp_bytes = strlen(np->nntp_command);
/* Before sending a request to the server, do a cleanup operation
to make sure that no more responses are coming from the server. */
NNMesrvr(np); /* End server read */
memcpy(np->client_buf,np->nntp_command,nntp_bytes);
np->client_buf[nntp_bytes ] = CARRIAGE_RETURN;
np->client_buf[nntp_bytes+1] = LINE_FEED;
if (np->receiving_text &&
nntp_bytes == 1 &&
np->client_buf[0] == '.') {
np->receiving_text = FALSE;
}
if (np->debug_mode)
NNMdump(np,"Writing to server",np->client_buf,nntp_bytes+2);
#ifdef MVS
EBCDIC_TO_ASCII(np->client_buf,nntp_bytes+2);
#endif
writrc = write(np->socknum, np->client_buf, nntp_bytes+2);
if (writrc < 0) {
np->connection_broken = TRUE;
if (!np->reconnect_in_progress) {
GETMAIN(s_buf,char,CLIENT_BUF_MSGSIZE+4,"socket buffer");
if (s_buf) {
memcpy(s_buf,np->client_buf,nntp_bytes+2);
if (NNMrecon(np)) { /* Reconnect to server */
writrc = write(np->socknum, s_buf, nntp_bytes+2);
}
FREEMAIN(s_buf, "old socket buffer");
}
}
}
if (writrc < 0) {
CRIT2("TCP/IP error: write() failed to send data to server %s.",
np->nnserver);
return FALSE;
}
NNMssrvr(np); /* Start server read */
return TRUE;
}
./ ADD NAME=NNMSOPT,SSI=01010012
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@SOPT ")
#pragma csect(static,"NN$SOPT ")
#include "nn.h"
#define BOOLOPTSET(A,B,C) \
switch (A[0]) { \
case 'n': \
case 'N': B = FALSE; break; \
case 'y': \
case 'Y': B = TRUE; break; \
case '\0': \
default: B = C; break; \
}
/****** Set options that are stored in ISPF profile. *****************/
void
NNMsopt(np,which)
Rstruc nncb *np;
enum user_option which;
{
int arrows;
char tempinc [256];
char tempexc [256];
char nnmupdtf[ 12];
char nnextpow[ 4];
char nnextpap[ 4];
char nnupan [ 4];
char nnuprn [ 4];
char nnupra [ 4];
char nnngscr [ 4];
char nnngcsr [ 4];
char nnarscr [ 4];
char nnarcsr [ 4];
char nnarrows[ 2];
if (which == OPTION_ALL) {
NNMispf(np, "VGET \
(NNRFCOPT NNRFCINC NNRFCEXC\
NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP\
NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS)\
PROFILE");
}
if (which == OPTION_ALL || which == OPTION_HEADER) {
(void)NNMivget(np,"NNRFCOPT ", np->nnrfcopt, sizeof(np->nnrfcopt));
(void)NNMivget(np,"NNRFCINC ", tempinc, sizeof(tempinc));
(void)NNMivget(np,"NNRFCEXC ", tempexc, sizeof(tempexc));
if (!*np->nnrfcopt) strcpy(np->nnrfcopt,"A");
sprintf(np->nnrfcinc," %s ",tempinc);
sprintf(np->nnrfcexc," %s ",tempexc);
}
if (which == OPTION_ALL || which == OPTION_OTHER) {
(void)NNMivget(np,"NNUPAN ", nnupan, sizeof(nnupan ));
(void)NNMivget(np,"NNUPRN ", nnuprn, sizeof(nnuprn ));
(void)NNMivget(np,"NNUPRA ", nnupra, sizeof(nnupra ));
(void)NNMivget(np,"NNMUPDTF ", nnmupdtf, sizeof(nnmupdtf));
(void)NNMivget(np,"NNEXTPOW ", nnextpow, sizeof(nnextpow));
(void)NNMivget(np,"NNEXTPAP ", nnextpap, sizeof(nnextpap));
/* 5 is a "reasonable" default, according to DDI */
if (nnmupdtf[0] == '\0') np->updatefreq = 5;
else if (EQUAL(nnmupdtf, "OFF")) np->updatefreq = -1;
else if (EQUAL(nnmupdtf, "ON")) np->updatefreq = 0;
else np->updatefreq = atoi(nnmupdtf);
BOOLOPTSET(nnupan, np->update_adding_newsgroups, FALSE);
BOOLOPTSET(nnuprn, np->update_rewriting_newsrc, TRUE);
BOOLOPTSET(nnupra, np->update_retrieving_articles, TRUE);
BOOLOPTSET(nnextpow, np->warn_overwrite, TRUE);
BOOLOPTSET(nnextpap, np->warn_append, TRUE);
if (!np->update_retrieving_articles) np->updatefreq = -1;
}
if (which == OPTION_ALL || which == OPTION_VIEW) {
(void)NNMivget(np,"NNNGSCR ", nnngscr, sizeof(nnngscr ));
(void)NNMivget(np,"NNNGCSR ", nnngcsr, sizeof(nnngcsr ));
(void)NNMivget(np,"NNARSCR ", nnarscr, sizeof(nnarscr ));
(void)NNMivget(np,"NNARCSR ", nnarcsr, sizeof(nnarcsr ));
(void)NNMivget(np,"NNARROWS ", nnarrows, sizeof(nnarrows));
BOOLOPTSET(nnngscr, np->newsgroup_autoscroll, TRUE);
BOOLOPTSET(nnngcsr, np->newsgroup_autocursor, FALSE);
BOOLOPTSET(nnarscr, np->article_autoscroll, TRUE);
BOOLOPTSET(nnarcsr, np->article_autocursor, FALSE);
switch (nnarrows[0]) {
case '1':
default: arrows = 1; break;
case '2': arrows = 2; break;
case '3': arrows = 3; break;
}
if (arrows != np->article_rows) {
np->article_rows = arrows;
np->article_criterion_changed = TRUE;
}
}
return;
}
./ ADD NAME=NNMSORT,SSI=01080050
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@SORT ")
#pragma csect(static,"NN$SORT ")
#include "nn.h"
/****** Compare articles by number. **********************************/
static int
compare_articles_by_number(wp1,wp2)
register const void *wp1;
register const void *wp2;
{
return
(VARK2PARTICLE(**(VARK **)wp1))->number
- (VARK2PARTICLE(**(VARK **)wp2))->number
;
}
/****** Compare articles by subject. *********************************/
static int
compare_articles_by_subject(wp1,wp2)
register const void *wp1;
register const void *wp2;
{
int answer;
answer = strcmp(
(VARK2PARTICLE(**(VARK **)wp1))->csubject,
(VARK2PARTICLE(**(VARK **)wp2))->csubject
);
if (answer == 0) return compare_articles_by_number(wp1,wp2);
else return answer;
}
/****** Make canonical subject. *************************************/
static char *
make_canonical_subject(spp,subject)
char **spp;
char *subject;
{
char *ip;
char *op;
char *rp;
int re_count;
if (!*subject) return "";
/* Scan past "re"s and count them up */
rp = *spp;
re_count = -1;
ip = subject - 3;
do {
ip = ip + 3 + strspn(ip + 3," \t");
re_count++;
} while (!memcmp(ip,"Re:",3) ||
!memcmp(ip,"re:",3) ||
/* !memcmp(ip,"rE:",3) || - do you really expect this??? */
!memcmp(ip,"RE:",3));
/* Copy subject to buffer while lowercasing. Sets op to last nonblank
character in buffer. */
copy_lowercase_and_strip_trailing(rp,ip,op);
/* Hack for prioritizing RE:'s. Add a byte at the end to put
* subjects in order. e.g.:
* Subject: Foo --> "foo\0"
* Subject: Re: Foo --> "foo\001\0"
* Subject: Re: Re: Foo --> "foo\002\0"
*
* This algorithm will break if there are more than 255 "RE:"s,
* but do you really think that's likely?
*/
if (re_count > 0) {
*op = (unsigned char) re_count;
op++;
}
*op = '\0';
*spp = op + 1; /* Bump buffer pointer past our new end */
return rp;
}
/****** Sort article table. *****************************************/
Bool
NNMsort(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
Rstruc newsarticle *ap;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
VARK **wp;
char *sortbuf;
char *sp;
int sortbufsize;
int count;
int i;
if (!gp->article_vector) return TRUE;
if (gp->sort_vector) {
FREEMAIN(gp->sort_vector,"sort vector");
gp->sort_vector = NULL;
gp->sort_count = 0;
}
/* Retrieve article titles, read or unread, but ignoring any
* subject filtering.
*/
count = NNMrart(np,gp,FALSE,TRUE); /* Retrieve article titles */
if (count == 0) return TRUE;
GETMAIN(gp->sort_vector, VARK **, count, "sort vector");
if (!gp->sort_vector) {
CRIT1("There is not enough memory to sort the newsgroup.");
return FALSE;
}
gp->sort_count = count;
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
wp = gp->sort_vector;
sortbufsize = 0;
for (vp = vpfirst; vp <= vplast; vp++) {
if (IsEligible(*vp)) { /* i.e. if NNMrart retrieved it */
ap = VARK2PARTICLE(*vp);
if (*ap->subject) sortbufsize += strlen(ap->subject) + 1;
SetUnknown(*vp); /* unfudge status as we go */
*(wp++) = vp;
}
}
if (sortbufsize > 0) {
GETMAIN(sortbuf, char, sortbufsize, "sort-by-subject buffer");
if (!sortbuf) {
CRIT1("There is not enough memory to sort articles by subject.");
FREEMAIN(gp->sort_vector,"sort vector");
gp->sort_vector = NULL;
gp->sort_count = 0;
return FALSE;
}
}
sp = sortbuf;
for (wp = gp->sort_vector, i = gp->sort_count; i > 0; wp++, i--) {
ap = VARK2PARTICLE(**wp);
ap->csubject = make_canonical_subject(&sp,ap->subject);
}
qsort(gp->sort_vector, gp->sort_count, sizeof(VARK **),
compare_articles_by_subject);
/* This isn't strictly necessary as long as no one tries to refer
* to ap->csubject outside of this module.
*
for (wp = gp->sort_vector, i = gp->sort_count; i > 0; wp++, i--) {
ap = VARK2PARTICLE(**wp);
ap->csubject = NULL;
}
*
*/
FREEMAIN(sortbuf,"sort-by-subject buffer");
return TRUE;
}
./ ADD NAME=NNMSSRVR,SSI=01000016
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@SSRVR")
#pragma csect(static,"NN$SSRVR")
#include "nn.h"
/****** Start server read. *******************************************/
void
NNMssrvr(np)
Rstruc nncb *np;
{
np->server_has_something_pending = TRUE;
np->server_finished_replying = FALSE;
np->sending_text = FALSE;
np->something_to_print = FALSE;
np->dont_read = FALSE;
return;
}
./ ADD NAME=NNMSTRLC,SSI=01000026
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@STRLC")
#pragma csect(static,"NN$STRLC")
#include "nn.h"
/****** Case-insensitive string search. ******************************/
/* This differs from the Ustrstr function in NNMbbexp in that it only
* has to lowercase the "b" argument, not both. The "a" argument
* is assumed to be all lower case already.
*/
char *
NNMstrlc(b,a)
register char *b;
register char *a;
{
register char *aa;
register char *bb;
if (!*a) return strchr(b,'\0');
for (;;) {
while (*b && (*a != tolower(*b))) b++;
if (!*b) return NULL;
for (aa = a, bb = b;
*aa && *bb && (*aa == tolower(*bb));
aa++, bb++) ;
if (!*aa) return a;
b++;
}
}
./ ADD NAME=NNMSUMAT,SSI=01000051
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@SUMAT")
#pragma csect(static,"NN$SUMAT")
#include "nn.h"
/****** Subject matching code. ***************************************/
Bool
NNMsumat(a,b)
char *a;
char *b;
{
char *cp;
char *c1;
char *c2;
char bracket;
char s1[257];
char s2[257];
strncpy(s1,a,256);
strncpy(s2,b,256);
lowercase_and_strip_trailing_in_place(s1);
lowercase_and_strip_trailing_in_place(s2);
c1 = skip_whitespace(s1);
c2 = skip_whitespace(s2);
if (!strcmp(c1,c2)) return TRUE;
while (!memcmp(c1,"re:",3)) {
c1 = skip_whitespace(c1+3);
if (!strcmp(c1,c2)) return TRUE;
}
while (!memcmp(c2,"re:",3)) {
c2 = skip_whitespace(c2+3);
if (!strcmp(c1,c2)) return TRUE;
}
if ((cp=strstr(c1,"(was:" /*)*/ )) ||
(cp=strstr(c1,"(was " /*)*/ )) ||
(cp=strstr(c1,"[was " /*)*/ )) ||
(cp=strstr(c1,"[was:" /*)*/ ))) {
switch (*cp) {
case '(': bracket = ')'; break;
case '[': bracket = ']'; break;
default: bracket = '\0'; break;
}
c1 = skip_whitespace(cp+5);
if (!memcmp(c1,"re:",3)) c1 = skip_whitespace(c1+3);
if (!strcmp(c1,c2)) return TRUE;
cp = c1 + strlen(c1) - 1;
if (*cp == bracket) *cp = '\0';
if (!strcmp(c1,c2)) return TRUE;
}
if ((cp=strstr(c2,"(was:" /*)*/ )) ||
(cp=strstr(c2,"(was " /*)*/ )) ||
(cp=strstr(c2,"[was " /*)*/ )) ||
(cp=strstr(c2,"[was:" /*)*/ ))) {
switch (*cp) {
case '(': bracket = ')'; break;
case '[': bracket = ']'; break;
default: bracket = '\0'; break;
}
c2 = skip_whitespace(cp+5);
if (!memcmp(c2,"re:",3)) c2 = skip_whitespace(c2+3);
if (!strcmp(c1,c2)) return TRUE;
cp = c2 + strlen(c2) - 1;
if (*cp == bracket) *cp = '\0';
if (!strcmp(c1,c2)) return TRUE;
}
if (!strcmp(c1,c2)) return TRUE;
return FALSE;
}
./ ADD NAME=NNMTSO,SSI=01000006
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/********************************************************************/
/* */
/* Thanks to Michael Van Norman for this code. */
/* */
/********************************************************************/
#pragma csect(code, "NN@TSO ")
#pragma csect(static,"NN$TSO ")
#include "nn.h"
#pragma linkage(ikjeftsr,OS)
#define _IKJEFTSR_FLAGS_AUTH 0x00000000
#define _IKJEFTSR_FLAGS_COMMAND 0x00000001
#define _IKJEFTSR_FLAGS_DUMP 0x00000100
#define _IKJEFTSR_FLAGS_NODUMP 0x00000000
#define _IKJEFTSR_FLAGS_PROGRAM 0x00000002
#define _IKJEFTSR_FLAGS_UNAUTH 0x00010000
/****** Issue TSO command. *******************************************/
int
NNMtso(command)
char *command;
{
int flags = _IKJEFTSR_FLAGS_COMMAND +
_IKJEFTSR_FLAGS_UNAUTH;
int commandLength = strlen(command);
int rc = 0;
int returnCode = 0;
int reasonCode = 0;
int abendCode = 0;
static int (*ikjeftsr)() = NULL;
if (!ikjeftsr) {
/*
ikjeftsr = (int (*)())fetch("ikjeftsr");
if (!ikjeftsr) {
*/
/* #pragma linkage( tsoServiceFacility, OS )
* int (*tsoServiceFacility)( int *, char *, int *,
* int *, int *, int * );
*/
int tsoEntryAddress;
tsoEntryAddress = 0x00000010; /* Address of CVT */
tsoEntryAddress = *(int *)(tsoEntryAddress);
tsoEntryAddress += 0x9C;/* /* Offset of TVT in CVT */
tsoEntryAddress = *(int *)(tsoEntryAddress);
tsoEntryAddress += 0x10;/* /* TSVTASF-TSVT (from IKJTSVT) */
tsoEntryAddress = *(int *)(tsoEntryAddress);
ikjeftsr = (int (*)())(tsoEntryAddress);
/*
}
*/
}
if (!ikjeftsr) {
fprintf(stderr,
"Cannot execute TSO commands, can't fetch IKJEFTSR.\n");
return -2;
}
rc = (*ikjeftsr)(&flags, command, &commandLength,
&returnCode, &reasonCode,
(int *)((int)(&abendCode) | 0x80000000));
if (rc != 0) {
if (rc > 4) {
fprintf(stderr,"Command failed:%s\n",command);
if (rc == 20 && reasonCode == 40)
fprintf(stderr,"Command was not found.\n");
else fprintf(stderr,
"rc=%d,returncode=%d,reasoncode=%d,abendcode=%8.8x\n",
rc, returnCode, reasonCode, abendCode);
}
if (abendCode != 0) rc = -1;
else rc = returnCode;
}
return rc;
}
./ ADD NAME=NNMUNALC,SSI=01010053
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@UNALC")
#pragma csect(static,"NN$UNALC")
#include "nn.h"
/****** Unallocate a data set. ***************************************/
Bool
NNMunalc(ddname)
char *ddname;
{
__S99parms stuff99; /* The manual has it wrong. No "struct". */
int rc;
TEXTUNIT *tu [2];
TEXTUNIT tu_ddn;
TEXTUNIT tu_una;
if (!ddname ||
!*ddname) return TRUE; /* if no ddname to free, do nothing */
memset((char *)&stuff99,0,sizeof(__S99parms));
stuff99.__S99RBLN = 20;
stuff99.__S99VERB = S99VRBUN;
stuff99.__S99FLAG1 = 0;
stuff99.__S99ERROR = 0;
stuff99.__S99INFO = 0;
stuff99.__S99TXTPP = tu;
stuff99.__S99FLAG2 = 0;
tu[0] = &tu_ddn;
tu[1] = &tu_una;
*(int *)&tu[1] |= 0x80000000;
tu_ddn.key = DUNDDNAM;
tu_ddn.num = 1;
tu_ddn.ent.len = strlen(ddname);
copy_uppercase(tu_ddn.ent.prm,ddname);
tu_una.key = DUNUNALC;
tu_una.num = 0;
rc = svc99(&stuff99);
if (rc == 0) return TRUE;
else if (stuff99.__S99ERROR == 0x0438) /* not freed, is not allocated*/
return TRUE;
else {
NNMdfail(rc,&stuff99);
return FALSE;
}
}
./ ADD NAME=NNMUPDT,SSI=01000017
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@UPDT ")
#pragma csect(static,"NN$UPDT ")
#include "nn.h"
/****** Update the screen as frequently as desired. ******************/
void
NNMupdt(np,cdp,screen)
Rstruc nncb *np;
struct countdown *cdp;
char *screen;
{
int pct;
int barsize;
int l;
int timediff;
int h;
int m;
int s;
time_t thistime;
char nnmbar[62];
char nnmestm[9];
char zhilite[9];
char temp[8];
char display_string[24];
if (!cdp || !cdp->do_update || np->batch_mode) return;
time(&thistime);
if (cdp->done == 0) {
if (cdp->to_do == 0) return;
if (np->barchar == '\0') {
(void)NNMivget(np,"ZHILITE ",zhilite,sizeof(zhilite));
if (zhilite[0] == 'Y') np->barchar = ' ';
else np->barchar = '@';
}
timediff = -1; /* don't display on initial call */
np->lasttime = thistime;
np->firstime = thistime;
memset(nnmestm,' ',sizeof(nnmestm));
(void)NNMivput(np, "NNMESTM ", nnmestm, 0);
}
else {
timediff = (int)difftime(thistime, np->lasttime);
}
if (timediff >= np->updatefreq) {
memset(nnmbar,' ',sizeof(nnmbar));
nnmbar[0] = '^';
if (cdp->to_do < 0) {
pct = 0;
barsize = 1;
}
else {
if (cdp->to_do < cdp->done) cdp->to_do = cdp->done;
pct = cdp->done * 100 / cdp->to_do;
barsize = pct * (sizeof(nnmbar) - 2) / 100 + 1;
}
memset(nnmbar+1, np->barchar, barsize-1);
nnmbar[barsize++] = '/';
#if 1
/* This code adds the number of currently processed items to the */
/* right of the bar until it won't fit anymore, then puts it */
/* inside the bar. */
l = sprintf(temp, "%d", cdp->done);
if (barsize + l < sizeof(nnmbar)) {
memcpy(&nnmbar[barsize], temp, l);
}
else {
memcpy(&nnmbar[barsize-l-3], temp, l);
if (np->barchar != ' ') {
nnmbar[barsize-l-4] = ' ';
nnmbar[barsize-3] = ' ';
}
}
#else
/* This code adds the number of currently processed items to the */
/* right of the bar until it will fit inside, then puts it there. */
l = sprintf(temp, "%d", cdp->done);
if (barsize - 4 < l + 2) {
memcpy(&nnmbar[barsize], temp, l);
}
else {
memcpy(&nnmbar[barsize-l-3], temp, l);
if (np->barchar != ' ') {
nnmbar[barsize-l-4] = ' ';
nnmbar[barsize-3] = ' ';
}
}
#endif
(void)NNMivput(np, "NNMBAR ",nnmbar,sizeof(nnmbar));
l = sprintf(temp, "%d", cdp->to_do);
(void)NNMivput(np, "NNMCOUNT", temp, l);
s = (cdp->to_do - cdp->done) * difftime(thistime, np->firstime)
/ cdp->done;
if (s > 0) {
m = s / 60; s = s % 60;
h = m / 60; m = m % 60;
sprintf(nnmestm, "%2.2d:%2.2d:%2.2d", h, m, s);
(void)NNMivput(np, "NNMESTM ", nnmestm, sizeof(nnmestm) - 1);
}
sprintf(display_string, "DISPLAY PANEL(%s)", screen);
(void)NNMispf(np, "CONTROL DISPLAY LOCK");
(void)NNMispf(np, display_string);
np->lasttime = thistime;
}
cdp->done++;
return;
}
./ ADD NAME=NNMVAR,SSI=01250015
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@VAR ")
#pragma csect(static,"NN$VAR ")
#include "nn.h"
#define ROWCPY(A,B,C) {\
name_length = strlen(B); \
if (name_length > C) name_length = C; \
memcpy(&rowp[A], B, name_length); \
}
struct ntdynarray {
struct newsarticle *article;
VARK **sortvark;
int number;
char numstr [6];
};
/****** Format screen line. ******************************************/
static void
format_screen_line(ap,vp,ndp,wp)
Rstruc newsarticle *ap;
VARK *vp;
Rstruc ntdynarray *ndp;
VARK **wp;
{
ndp->sortvark = wp;
ndp->article = ap;
ndp->number = ap->number;
sprintf(ndp->numstr, "%5d", ndp->number);
if (ap->action == NO_ACTION) {
if (IsRead(*vp)) ap->action = READ;
else ap->action = UNREAD;
}
return;
}
/****** View articles. ***********************************************/
static Bool
view_articles(np,gp,dynarray,nntdyna,depth,dynsize)
Rstruc nncb *np;
Rstruc newsgroup *gp;
struct ntdynarray *dynarray;
char *nntdyna;
int depth;
int dynsize;
{
struct newsarticle *ap;
Rstruc ntdynarray *ndp;
Rstruc tabledesc *tdp;
Rstruc seldesc *sdp;
Rstruc cmddesc *cdp;
struct ntdynarray *ntdynarray_start;
struct ntdynarray *ntdynarray_end;
char *cp;
char *rowp;
char *act;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
VARK **wp;
VARK **wpfirst;
VARK **wplast;
VARK **save_top_sorted_article;
int save_top_article;
int display_total;
int command_index;
int prc;
int nntlvl;
int articles_per_screen;
int scroll;
int zscrolln;
int rowincr;
int rowbump;
int actlen;
int anum;
int artcursor;
int last_article_selected;
short name_length;
Bool is_max;
Bool is_scroll_word;
Bool rebuild_dynamic_array;
Bool selection_processed_ok;
Bool command_processed_ok;
char aattr;
char sel;
struct countdown cd;
char tcmd [72];
char nnthead [81];
char nntcsr [12];
char command [COMMANDSIZE];
char zverb [9];
char zscrolla [9];
char rowmessage [81];
ntdynarray_start = dynarray;
rebuild_dynamic_array = TRUE;
scroll = 0;
artcursor = 0;
last_article_selected = -1;
save_top_article = 0;
save_top_sorted_article = NULL;
tdp = np->display_table_vector->article_display_table;
strcpy(tcmd,"");
strcpy(np->article_only_string,"");
cd.do_update = (np->updatefreq >= 0);
cd.done = 0;
cd.to_do = -1;
/* Loop displaying article titles until END. */
do {
/* The very first time, all articles have a not-known-yet status.
* The normal article collections set knownness on the fly.
* When the article criterion changes (e.g. ONLY command),
* all articles are set to unknown. This could also be done
* in processing for the ONLY command itself.
* If status has been changed (read->unread or vice versa),
* alter it here. But do not change it if the status is read
* and the displayed status has been set to one of those
* funny values like "Extracted".
* This is needed because the newsgroup mark and unmark
* operations do not go through the ap actions.
*/
if (np->article_criterion_changed) {
if (gp->sort_vector) (void)NNMsort(np,gp);
np->article_criterion_changed = FALSE;
rebuild_dynamic_array = TRUE;
if (gp->article_vector) {
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
SetUnknown(*vp);
if (IsPresent(*vp) && (ap=VARK2PARTICLE(*vp))) {
if (IsRead(*vp)) {
if (ap->action == UNREAD
|| ap->action == MISSING
|| ap->action == ERROR
|| ap->action == NO_ACTION) ap->action = READ;
else;
}
else ap->action = UNREAD;
}
}
}
} /* end if article criterion changed */
/*
* If necessary, rebuild the array of newsarticle pointers.
*/
if (rebuild_dynamic_array) {
rebuild_dynamic_array = FALSE;
rowincr = np->article_rows;
if (rowincr < 1) rowincr = 1;
rowbump = 80 * rowincr;
articles_per_screen = (depth-1)/rowincr + 1;
cd.do_update = (np->updatefreq >= 0);
cd.done = 0;
cd.to_do = articles_per_screen;
display_total = articles_per_screen;
ndp = ntdynarray_start;
/* Process scroll, collecting (abs(scroll)) articles
* until the new top-of-display article is found. Logic:
* If top article is logically past end, then OK.
* If top article is not eligible, move back up until we find
* an eligible one.
* If top article is first but still not eligible, move down
* until we find an eligible one.
* Then collect enough articles to fill the screen.
*/
if (gp->sort_vector) {
wpfirst = gp->sort_vector;
wplast = gp->sort_vector + gp->sort_count;
wp = np->top_sorted_article;
if (wp < wplast) {
for (; wp >= wpfirst; wp--)
if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) break;
}
if (wp < wpfirst) {
for (wp = wpfirst; wp < wplast; wp++)
if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) break;
}
if (scroll > 0) {
while (scroll > 0 && ++wp < wplast) {
if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) scroll--;
}
}
else if (scroll < 0) {
while (scroll < 0 && --wp >= wpfirst) {
if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) scroll++;
}
if (wp < wpfirst) wp = wpfirst;
}
np->top_sorted_article = wp;
for (; display_total > 0 && wp < wplast; wp++) {
if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)) {
format_screen_line(ap,*wp,ndp,wp);
display_total--;
ndp++;
}
}
ntdynarray_end = ndp;
}
else if (gp->article_vector) { /* not sorted */
anum = np->top_article;
if (anum <= gp->vector_last) {
for (; anum >= gp->vector_first; anum--)
if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) break;
}
if (anum < gp->vector_first) {
for (anum = gp->vector_first; anum <= gp->vector_last; anum++)
if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) break;
}
if (scroll > 0) {
while (scroll > 0 && ++anum <= gp->vector_last) {
if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) scroll--;
}
}
else if (scroll < 0) {
while (scroll < 0 && --anum >= gp->vector_first) {
if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) scroll++;
}
if (anum < gp->vector_first) anum = gp->vector_first;
}
np->top_article = anum;
for (; display_total > 0 && anum <= gp->vector_last; anum++) {
if (NNMcar(np,gp,anum,NULL,&ap,&cd,RETRIEVE)) {
vp = &GETVARK(gp,anum);
format_screen_line(ap,vp,ndp,NULL);
display_total--;
ndp++;
}
}
ntdynarray_end = ndp;
} /* end not sorted */
else { /* no article vector */
ntdynarray_end = ndp;
np->top_article = 0;
}
} /* end if rebuild_dynamic_array */
save_top_article = np->top_article;
save_top_sorted_article = np->top_sorted_article;
artcursor = 0;
/* Fill dynamic area with data for groups satisfying criterion. */
memset(nntdyna, ' ', dynsize);
for (ndp = ntdynarray_start, rowp = nntdyna;
ndp < ntdynarray_end;
ndp++) {
ap = ndp->article;
if (np->article_autocursor
&& ndp->number == last_article_selected) {
artcursor = rowp + 2 - nntdyna;
}
rowp[ 0] = DATAIN_HIGH; /* selection code attribute */
rowp[ 1] = ' '; /* selection code field */
rowp[ 2] = DATAOUT_BLUE; /* article number attribute */
memcpy(&rowp[ 3], ndp->numstr, 5); /* article number */
rowp[ 8] = DATAOUT_GREEN; /* article title attribute */
ROWCPY(9,ap->subject,60); /* article title */
switch (ap->action) {
case NO_ACTION: act = "No action"; aattr = DATAOUT_TURQ; break;
case READ: act = "Read " ; aattr = DATAOUT_BLUE; break;
case RETRIEVED: act = "Retrieved"; aattr = DATAOUT_BLUE; break;
case EXTRACTED: act = "Extracted"; aattr = DATAOUT_BLUE; break;
case PRINTED: act = "Printed" ; aattr = DATAOUT_BLUE; break;
case UNREAD: act = "Unread " ; aattr = DATAOUT_YELLOW; break;
case MISSING: act = "Missing" ; aattr = DATAOUT_TURQ; break;
case ERROR: act = "Error " ; aattr = DATAOUT_TURQ; break;
case CANCELLED: act = "Cancelled"; aattr = DATAOUT_BLUE; break;
default: act = "???????" , aattr = DATAOUT_TURQ; break;
}
actlen = strlen(act);
memcpy(&rowp[68-actlen],act,actlen);
rowp[68-actlen-1] = aattr;
if (rowincr == 1) {
rowp[68] = DATAOUT_GREEN; /* article date attribute */
ROWCPY(69,ap->date,11); /* article date */
}
else {
memset(&rowp[68],' ',12);
}
if ((rowp+=80) >= nntdyna + dynsize) break;
if (rowincr >= 2) {
rowp[0] = DATAOUT_GREEN; /* article author attribute */
ROWCPY(9,ap->from,58); /* article author */
rowp[59] = DATAOUT_GREEN; /* article date attribute */
ROWCPY(60,ap->date,20); /* article date */
if ((rowp+=80) >= nntdyna + dynsize) break;
if (rowincr >= 3) {
rowp[0] = DATAOUT_BLUE;
ROWCPY(9,ap->message_id,70);
if ((rowp+=80) >= nntdyna + dynsize) break;
}
}
} /* end for */
if (rowp < nntdyna + dynsize) {
rowp[0] = DATAOUT_HIGH;
memset(&rowp[1], '-',79);
}
/* Format the heading line for the title display.
* Row message is "Range mmmm-nnnn", not "m-n of p", because
* we don't always know if we can get to all the articles.
*/
if (!gp->article_vector) strcpy(rowmessage, "");
else sprintf(rowmessage, " Range %d-%d",
gp->vector_first, gp->vector_last);
memset(nnthead, '-', 80);
*(nnthead+80) = '\0';
strcpy(nnthead, "Newsgroup: ");
name_length = strlen(gp->name);
if (name_length > 40) name_length = 40;
strncat(nnthead, gp->name, name_length);
*(strchr(nnthead,'\0')) = ' ';
strcpy(nnthead + 79 - strlen(rowmessage), rowmessage);
if (artcursor > 0) {
sprintf(nntcsr,"%d",artcursor);
(void)NNMivput(np,"NNTCSR ", nntcsr, -1);
}
else {
(void)NNMivput(np,"NNTCSR ", "0", 1);
}
(void)NNMivput(np,"NNTCMD " , tcmd, -1);
(void)NNMivput(np,"NNTHEAD ", nnthead, -1);
(void)NNMivput(np,"NNTDYNA ", nntdyna, dynsize);
(void)NNMivput(np,"YRFIND " ,"ALIAS FIND",-1);
prc = NNMdispl(np,"NNMDAR ");
if (prc > 8) break;
(void)NNMivput(np,"YRFIND " ,"",-1);
(void)NNMivget(np,"NNTDYNA " , nntdyna, dynsize);
(void)NNMivget(np,"ZVERB " , zverb, sizeof(zverb));
(void)NNMivget(np,"ZSCROLLA ", zscrolla, sizeof(zscrolla));
zscrolln = NNMiget(np,"ZSCROLLN ");
nntlvl = NNMiget(np,"NNTLVL ");
scroll = 0;
/* Process selections. */
save_top_article = np->top_article;
save_top_sorted_article = np->top_sorted_article;
np->top_article = 0;
np->top_sorted_article = NULL;
last_article_selected = -1;
for (ndp = ntdynarray_start, rowp = nntdyna;
ndp < ntdynarray_end && !np->quit;
ndp++, rowp += rowbump) {
sel = toupper(rowp[1]);
if (sel == ' ') continue;
for (sdp = tdp->first_seldesc; sdp->selection_code != ' '; sdp++) {
if (sel == sdp->selection_code) {
ap = ndp->article;
np->current_sortvark = ndp->sortvark;
selection_processed_ok = (sdp->selection_processor)(np,ap);
last_article_selected = ap->number;
sdp = NULL;
break;
}
}
if (sdp) {
ERR1("Unknown selection code. Type one of the listed codes.");
selection_processed_ok = FALSE;
}
}
if (np->quit) break;
if (np->top_article != 0 && np->article_autocursor)
last_article_selected = np->top_article;
if (np->top_article == 0 || !np->article_autoscroll)
np->top_article = save_top_article;
if (np->top_sorted_article == NULL || !np->article_autoscroll)
np->top_sorted_article = save_top_sorted_article;
/* Process command if any. */
strcpy(tcmd,"");
(void)NNMivget(np,tdp->command_variable,tcmd,sizeof(tcmd));
if (strcmp(tcmd,"") != 0) {
last_article_selected = -1;
memset(command,' ',COMMANDSIZE);
command_index = 0;
for (cp = tcmd; *cp && !isspace(*cp); cp++) {
if (cp >= tcmd+COMMANDSIZE) {
ERR1("Unknown command name.");
command_processed_ok = FALSE;
}
command[command_index++] = toupper(*cp);
}
while (*cp && isspace(*cp)) cp++;
for (cdp = tdp->first_cmddesc; *cdp->command_name != ' '; cdp++) {
if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
command_processed_ok = (cdp->command_processor)(np,gp,cp);
cdp = NULL;
break;
}
}
if (cdp) {
for (cdp=tdp->next_cmddesc; *cdp->command_name != ' '; cdp++) {
if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
command_processed_ok = (cdp->command_processor)(np,gp,cp);
cdp = NULL;
break;
}
}
}
if (cdp) {
ERR1("Unknown command name.");
command_processed_ok = FALSE;
}
if (command_processed_ok) strcpy(tcmd,"");
}
if (np->quit) break;
if (np->top_article != save_top_article
|| np->top_sorted_article != save_top_sorted_article)
rebuild_dynamic_array = TRUE;
/* Process scroll request if any. */
switch (zscrolla[0]) {
case 'P':
case 'H':
case 'C':
case 'D': is_max = FALSE;
is_scroll_word = TRUE;
break;
case 'M': is_max = TRUE;
break;
default: is_max = FALSE;
is_scroll_word = FALSE;
break;
}
if (EQUAL(zverb,"DOWN")) {
if (is_max) {
np->top_article = gp->vector_last;
np->top_sorted_article = wplast - 1;
scroll = -((nntlvl-1)/np->article_rows);
}
else
if (is_scroll_word) scroll = zscrolln/rowincr;
else scroll = zscrolln;
}
else if (EQUAL(zverb,"UP")) {
if (is_max) {
np->top_article = gp->vector_first;
np->top_sorted_article = wpfirst;
scroll = 0;
rebuild_dynamic_array = TRUE;
}
else
if (is_scroll_word) scroll = -zscrolln/rowincr;
else scroll = -zscrolln;
}
else scroll = 0;
if (scroll != 0) rebuild_dynamic_array = TRUE;
} while (prc == 0);
return TRUE;
}
/****** View articles. ***********************************************/
Bool
NNMvar(np,gp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
{
struct ntdynarray *dynarray;
char *nntdyna;
int depth;
int dynsize;
/* Get depth of dynamic area (number of rows to display on screen) */
(void)NNMispf(np,
"PQUERY PANEL(NNMDAR) AREANAME(NNTDYNA) DEPTH(NNTDEPTH)");
if (np->ispfrc != 0) return FALSE;
depth = NNMiget(np,"NNTDEPTH ");
/* Allocate a block of "ntdynarray" article pointers, one element
* for each article currently being displayed. This must be big
* enough to fill up the screen. It is rebuilt every time the
* display changes, through scrolling or selection activity.
*/
GETMAIN(dynarray, struct ntdynarray, depth,
"newsarticle dynamic array");
if (!dynarray) return FALSE;
/* Get storage for ISPF dynamic area variable to be constructed. */
dynsize = 80*depth;
GETMAIN(nntdyna, char, dynsize+1, "NNTDYNA buffer");
if (!nntdyna) return FALSE;
np->top_article = 0;
np->top_sorted_article = NULL;
np->repeat_find = FALSE;
np->article_criterion_changed = TRUE;
*np->selsubj = '\0';
if (!view_articles(np,gp,dynarray,nntdyna,depth,dynsize)) return FALSE;
FREEMAIN(nntdyna,"NNTDYNA buffer");
FREEMAIN(dynarray,"newsarticle dynamic area");
return TRUE;
}
./ ADD NAME=NNMVIEW,SSI=01460008
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@VIEW ")
#pragma csect(static,"NN$VIEW ")
#include "nn.h"
struct browser {
struct newsgroup *gp;
struct newsarticle *ap;
struct texthdr *thp; /* text header pointer */
struct textline **tv; /* text vector */
char *bda; /* dynamic area address */
char *work; /* find work area address */
char *firstpos; /* beginning of actual data */
char *lastpos; /* end of actual data */
int depth; /* dynamic area depth */
int lvl; /* last visible line */
int size; /* dynamic area size */
int more_rows; /* Scroll request row count */
int rowfactor; /* # physical rows per line */
int screenbump; /* # physical rows * width */
int top; /* top row number */
int total; /* total number of rows */
int coloff; /* offset from LEFT/RIGHT */
int cols; /* 1 if COLS done, else 0 */
int maxlen; /* maximum text length */
int maxcoloff; /* maximum right scroll */
Bool override_scroll;/* set by some commands */
Bool highlighted; /* set if FIND highlights */
Bool reinit_browse; /* set if text changed */
Bool exit_browse; /* set if browse must exit */
Bool find_hit_end; /* top/bottom of data reach */
int find_count; /* used by FIND ALL */
int find_row; /* row where last found */
int find_col; /* col where last found */
int found_row; /* row where last found */
int found_col; /* col where last found */
int csrpos; /* cursor position */
int find_csrpos; /* col where last found */
int found_left; /* pos left of found string */
int found_right; /* pos right of found string*/
char cursor [9]; /* cursor field name */
char find_cursor[9]; /* row where last found */
char title [81]; /* title */
char cols_line [81]; /* cols line */
char zcmd [81]; /* command input */
};
/******* torot13 ******************************************************/
static char
torot13(c)
char c;
{
char d;
if (!isalpha(c)) d = c;
else switch (c) {
case 'a': d = 'n'; break;
case 'b': d = 'o'; break;
case 'c': d = 'p'; break;
case 'd': d = 'q'; break;
case 'e': d = 'r'; break;
case 'f': d = 's'; break;
case 'g': d = 't'; break;
case 'h': d = 'u'; break;
case 'i': d = 'v'; break;
case 'j': d = 'w'; break;
case 'k': d = 'x'; break;
case 'l': d = 'y'; break;
case 'm': d = 'z'; break;
case 'n': d = 'a'; break;
case 'o': d = 'b'; break;
case 'p': d = 'c'; break;
case 'q': d = 'd'; break;
case 'r': d = 'e'; break;
case 's': d = 'f'; break;
case 't': d = 'g'; break;
case 'u': d = 'h'; break;
case 'v': d = 'i'; break;
case 'w': d = 'j'; break;
case 'x': d = 'k'; break;
case 'y': d = 'l'; break;
case 'z': d = 'm'; break;
case 'A': d = 'N'; break;
case 'B': d = 'O'; break;
case 'C': d = 'P'; break;
case 'D': d = 'Q'; break;
case 'E': d = 'R'; break;
case 'F': d = 'S'; break;
case 'G': d = 'T'; break;
case 'H': d = 'U'; break;
case 'I': d = 'V'; break;
case 'J': d = 'W'; break;
case 'K': d = 'X'; break;
case 'L': d = 'Y'; break;
case 'M': d = 'Z'; break;
case 'N': d = 'A'; break;
case 'O': d = 'B'; break;
case 'P': d = 'C'; break;
case 'Q': d = 'D'; break;
case 'R': d = 'E'; break;
case 'S': d = 'F'; break;
case 'T': d = 'G'; break;
case 'U': d = 'H'; break;
case 'V': d = 'I'; break;
case 'W': d = 'J'; break;
case 'X': d = 'K'; break;
case 'Y': d = 'L'; break;
case 'Z': d = 'M'; break;
}
return d;
}
/******* EXTRACT command **********************************************/
static Bool
process_extract_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
Rstruc newsarticle *ap = bp->ap;
if (!ap) (void)NNMivput(np,"NNTNUM ","",-1);
np->extract_file = NULL;
np->printing = FALSE;
(void)NNMispf(np,"CONTROL DISPLAY SAVE");
(void)NNMxtx(np,ap,TRUE); /* Extract text */
(void)NNMispf(np,"CONTROL DISPLAY RESTORE");
return TRUE;
}
/******* PRINT command ************************************************/
static Bool
process_print_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
Rstruc newsarticle *ap = bp->ap;
if (!ap) (void)NNMivput(np,"NNTNUM ","",-1);
np->extract_file = NULL;
np->printing = TRUE;
(void)NNMispf(np,"CONTROL DISPLAY SAVE");
(void)NNMxtx(np,ap,TRUE); /* Print text */
(void)NNMispf(np,"CONTROL DISPLAY RESTORE");
return TRUE;
}
/******* UNREAD command ***********************************************/
static Bool
process_unread_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = UNREAD_THIS_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* ROT13 command ************************************************/
static Bool
process_rot13_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
struct textline *tp;
char *cp;
char *cpe;
for (tp=bp->thp->first_text_line; tp; tp=tp->next) {
for (cp=tp->tab_expanded_text, cpe=cp+tp->tab_expanded_text_length;
cp < cpe;
cp++) {
*cp = torot13(*cp);
}
}
bp->reinit_browse = TRUE;
return TRUE;
}
/******* REPLY command ************************************************/
static Bool
process_reply_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
(void)NNMispf(np,"CONTROL DISPLAY SAVE");
NNMdmail(np,bp->gp,bp->ap); /* Send mail message */
(void)NNMispf(np,"CONTROL DISPLAY RESTORE");
return TRUE;
}
/******* FOLLOWUP command *********************************************/
static Bool
process_followup_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
(void)NNMispf(np,"CONTROL DISPLAY SAVE");
NNMdpost(np,bp->gp,bp->ap); /* Post followup */
(void)NNMispf(np,"CONTROL DISPLAY RESTORE");
return TRUE;
}
/******* NEXT command *************************************************/
static Bool
process_next_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = NEXT_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* PREV command *************************************************/
static Bool
process_prev_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = PREV_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* NEXTU command ************************************************/
static Bool
process_nextu_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = NEXT_UNREAD_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* PREVU command ************************************************/
static Bool
process_prevu_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = PREV_UNREAD_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* NEXTT command ************************************************/
static Bool
process_nextt_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = NEXT_TABLED_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* PREVT command ************************************************/
static Bool
process_prevt_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = PREV_TABLED_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* NEXTSUBJ command *********************************************/
static Bool
process_nextsubj_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = NEXT_THREAD_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* PREVSUBJ command *********************************************/
static Bool
process_prevsubj_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = PREV_THREAD_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* FIRSTSUBJ command ********************************************/
static Bool
process_firstsubj_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = FIRST_THREAD_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* LASTSUBJ command *********************************************/
static Bool
process_lastsubj_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = LAST_THREAD_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* NEWSUBJ command **********************************************/
static Bool
process_newsubj_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
np->another_article = NEW_THREAD_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* SUBJECT command **********************************************/
static Bool
process_subject_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
/* If anything remaining on the command line, make it the new */
/* subject, otherwise just display the current subject. */
if (*operands) {
memset(np->selsubj,0,sizeof(np->selsubj));
strncpy(np->selsubj,operands,sizeof(np->selsubj)-1);
WARN1(
"Subject changed. All subject searches will use the new subject.");
}
else if (!*np->selsubj) {
WARN1(
"No current subject has been set by a subject-related command.");
}
else {
WARN2("Current subject: %s", np->selsubj);
}
return TRUE;
}
/******* OPTIONS command **********************************************/
static Bool
process_options_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
NNMdsopt(np,operands); /* Do "set options" function */
np->another_article = REDISPLAY_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* HEADERS command **********************************************/
static Bool
process_headers_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
NNMdsopt(np,"1"); /* Do "set options 1" function */
np->another_article = REDISPLAY_ARTICLE;
bp->exit_browse = TRUE;
return TRUE;
}
/******* COLS command *************************************************/
static Bool
process_cols_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
bp->cols = 1;
*bp->cols_line = '\0';
bp->reinit_browse = TRUE;
return TRUE;
}
/******* RESET command ************************************************/
static Bool
process_reset_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
bp->cols = 0;
*bp->cols_line = '\0';
bp->reinit_browse = TRUE;
return TRUE;
}
/******* DISPLAY command **********************************************/
static Bool
process_display_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
unsigned int u;
switch (strlen(operands)) {
case 1: np->text_dispchar = operands[0];
break;
case 2: if (1 != sscanf(operands,"%x",&u)) {
ERR1("Invalid hex character representation.");
return FALSE;
}
np->text_dispchar = u;
break;
default:
ERR1("A single character must be specified.");
return FALSE;
}
bp->reinit_browse = TRUE;
return TRUE;
}
/******* LOCATE command ***********************************************/
static Bool
process_locate_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
int locnum;
char junk[72];
if (1 != sscanf(operands, "%d %s", &locnum, junk)) {
ERR1("The LOCATE command requires a line number.");
return FALSE;
}
bp->top = locnum;
bp->more_rows = 0;
bp->override_scroll = TRUE;
bp->reinit_browse = TRUE;
return TRUE;
}
/***** Helper functions for FIND **************************************/
/*--------------------------------------------------------------------*
* Get quoted FIND string. *
*--------------------------------------------------------------------*/
static char *
get_quoted_find_string(np,cp,qform)
Rstruc nncb *np;
char *cp;
char *qform;
{
char quote = *cp;
char termchar = '\0';
for (cp++;;cp++) {
if (*cp == quote) {
switch (*(cp+1)) {
case '\0':
case ' ': termchar = '\0'; break;
case 'c':
case 'C': termchar = 'C' ; break;
case 't':
case 'T': termchar = 'T' ; break;
case 'x':
case 'X': termchar = 'X' ; break;
case 'p':
case 'P': termchar = 'P' ; break;
default: continue;
}
if (termchar) {
switch (*(cp+2)) {
case '\0':
case ' ': break;
default: continue;
}
if (*qform != FIND_QUOTED) {
ERR1(
"Invalid string; Do not surround a quoted string with letters.");
*qform = FIND_BADFORM;
return NULL;
}
else {
switch (termchar) {
case 'C': *qform = FIND_C; break;
case 'T': *qform = FIND_T; break;
case 'X': *qform = FIND_X; break;
case 'P': *qform = FIND_P; break;
}
*cp = '\0'; /* kill the quote because it's the character */
cp++; /* that the caller will kill, not the quote */
}
}
break;
}
else if (!*cp) {
ERR1(
"Missing quote; The FIND command requires balanced quote marks.");
*qform = FIND_BADFORM;
return NULL;
}
}
return cp;
}
/*--------------------------------------------------------------------*
* Get FIND operand. *
*--------------------------------------------------------------------*/
static char *
get_find_operand(np,opp,qform)
Rstruc nncb *np;
char **opp;
char *qform;
{
char *cp = *opp;
char *start = NULL;
cp = skip_ISPF_whitespace(cp);
if (!*cp) return NULL;
if (*cp == '\'' || *cp == '"') {
start = cp+1;
*qform = FIND_QUOTED;
if (!(cp = get_quoted_find_string(np,cp,qform))) return NULL;
}
else if ((*(cp+1) == '\'' || *(cp+1) == '"')) {
switch (*cp) {
case 'c':
case 'C': *qform = FIND_C; break;
case 't':
case 'T': *qform = FIND_T; break;
case 'x':
case 'X': *qform = FIND_X; break;
case 'p':
case 'P': *qform = FIND_P; break;
default: *qform = FIND_UNQUOTED; break;
}
if (*qform != FIND_UNQUOTED) {
cp++;
start = cp+1;
if (!(cp = get_quoted_find_string(np,cp,qform))) return NULL;
}
else {
start = cp;
find_ISPF_whitespace(cp,start);
}
}
else {
start = cp;
*qform = FIND_UNQUOTED;
find_ISPF_whitespace(cp,start);
}
if (*cp) {
*cp = '\0';
*opp = cp+1;
}
else {
*opp = cp;
}
return start;
}
/*--------------------------------------------------------------------*
* Find it. *
*--------------------------------------------------------------------*/
#define REND (r+(*tpp)->tab_expanded_text_length)
#define PRECEDED_BY_VERBIAGE (q>r && isalnum(*(q-1)))
#define FOLLOWED_BY_VERBIAGE (q+findlen<REND && isalnum(*(q+findlen)))
static Bool
find_it(np,bp,find_string,findlen,
find_type,find_what,find_trans,
find_left_bound,find_right_bound)
Rstruc nncb *np;
Rstruc browser *bp;
char *find_string;
int findlen;
char find_type; /* chars word prefix suffix */
char find_what; /* next prev first last all */
char find_trans; /* caps asis generic */
int find_left_bound;
int find_right_bound;
{
struct textline **tpp;
char *p;
char *q;
char *r;
int row;
int col;
int complen;
int lcol;
int rcol;
int ecol;
Bool backward_find;
lcol = find_left_bound - 1;
rcol = find_right_bound - 1;
row = bp->find_row;
col = bp->find_col;
switch (find_what) {
case FIND_NEXT:
if (bp->find_hit_end) {
bp->find_hit_end = FALSE;
row = 0;
col = lcol;
}
else if (EQUAL(bp->find_cursor,"NNBDYNA")) {
row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
col = (bp->find_csrpos-1) % 80 + bp->coloff;
if (++col >= bp->maxlen) {
row++;
col = lcol;
}
}
else {
row = bp->top - 1;
if (row < 0) row = 0;
col = lcol;
}
backward_find = FALSE;
break;
case FIND_PREV:
if (bp->find_hit_end) {
bp->find_hit_end = FALSE;
row = bp->total - 1;
col = rcol;
}
else if (EQUAL(bp->find_cursor,"NNBDYNA")) {
row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
col = (bp->find_csrpos-1) % 80 + bp->coloff;
if (--col < 0) {
row--;
col = rcol;
}
}
else {
row = bp->total - 1;
col = rcol;
}
backward_find = TRUE;
break;
case FIND_FIRST:
if (bp->find_hit_end) {
bp->find_hit_end = FALSE;
}
row = 0;
col = lcol;
backward_find = FALSE;
break;
case FIND_LAST:
if (bp->find_hit_end) {
bp->find_hit_end = FALSE;
}
row = bp->total - 1;
col = rcol;
backward_find = TRUE;
break;
case FIND_ALL:
col++;
backward_find = FALSE;
break;
}
if (backward_find == FALSE) {
/* forward find */
if (col < lcol) col = lcol;
else if (col > rcol) {
col = lcol;
row++;
}
for (tpp = &bp->tv[row]; row < bp->total; tpp++, col=lcol, row++) {
ecol = (*tpp)->tab_expanded_text_length - 1;
if (ecol > rcol) ecol = rcol;
if (col > ecol) continue;
p = (*tpp)->tab_expanded_text;
if (find_trans == FIND_CAPS) {
copy_uppercase(bp->work,p);
r = bp->work;
}
else r = p;
complen = ecol-col+1;
for (q = r + col;;q++) {
q = memchr(q,find_string[0],complen);
if (!q) break;
col = q - r;
complen = ecol-col+1;
if (complen < findlen) break;
if (!memcmp(q,find_string,findlen)) {
switch (find_type) {
case FIND_CHARS: break;
case FIND_WORD:
if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
continue;
break;
case FIND_PREFIX:
if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
continue;
break;
case FIND_SUFFIX:
if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
continue;
break;
}
bp->find_row = row;
bp->find_col = col;
return TRUE;
}
}
}
bp->find_row = 0;
bp->find_col = 0;
bp->find_hit_end = TRUE;
return FALSE;
}
else {
/* backward find */
if (row >= bp->total) row = bp->total - 1;
if (col > rcol-findlen+1) col = rcol-findlen+1;
else if (col < lcol) {
col = rcol-findlen+1;
row--;
}
for (tpp=&bp->tv[row]; row >= 0; tpp--, col=rcol-findlen+1, row--) {
ecol = (*tpp)->tab_expanded_text_length - 1;
if (ecol > rcol) ecol = rcol;
if (col > ecol) col = ecol;
p = (*tpp)->tab_expanded_text;
if (find_trans == FIND_CAPS) {
copy_uppercase(bp->work,p);
r = bp->work;
}
else r = p;
for (q = r + col; q >= r; q--) {
if (!memcmp(q,find_string,findlen)) {
switch (find_type) {
case FIND_CHARS: break;
case FIND_WORD:
if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
continue;
break;
case FIND_PREFIX:
if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
continue;
break;
case FIND_SUFFIX:
if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
continue;
break;
}
col = q - r;
bp->find_row = row;
bp->find_col = col;
return TRUE;
}
}
}
bp->find_row = bp->total - 1;
bp->find_col = bp->maxlen;
bp->find_hit_end = TRUE;
return FALSE;
}
}
/********* FIND command ***********************************************/
static Bool
process_find_command(np,bp,operands)
Rstruc nncb *np;
Rstruc browser *bp;
char *operands;
{
char *find_operand [64];
char *show_type;
char *cp;
char *opcopy;
char *op;
char *p;
char *q;
char find_qform [64];
Bool finderror = FALSE;
Bool out_of_bounds = FALSE;
int find_operand_count;
int ox;
int find_left_bound;
int find_right_bound;
int n;
int len;
int findlen;
char find_what; /* next prev first last all */
char find_type; /* chars word prefix suffix */
char find_trans; /* caps asis generic */
char find_form; /* unquoted quoted c x t p */
char ff; /* unquoted quoted c x t p */
Bool hit_end = FALSE;
Bool find_string_given = FALSE;
Bool find_what_given = FALSE;
Bool find_type_given = FALSE;
Bool find_left_bound_given = FALSE;
Bool find_right_bound_given = FALSE;
char operand_copy [81];
char find_string [81];
char temp [81];
char show_string [129];
char shortmsg [129];
char longmsg [129];
strcpy(operand_copy,operands);
find_operand_count = 0;
for (ox = 0, opcopy = operand_copy; ox < 64; ox++) {
ff = FIND_UNQUOTED;
op = get_find_operand(np,&opcopy,&ff);
if (ff == FIND_BADFORM) return FALSE;
if (!op) break;
find_operand[ox] = op;
find_qform[ox] = ff;
find_operand_count++;
}
if (find_operand_count == 0) {
if (!*np->text_find_string) {
ERR1("The first FIND command requires an operand.");
return FALSE;
}
strcpy(find_string,np->text_find_string);
find_what = np->text_find_what;
find_type = np->text_find_type;
find_trans = np->text_find_trans;
find_left_bound = np->text_find_left_bound;
find_right_bound = np->text_find_right_bound;
}
else {
find_what = FIND_NEXT;
find_type = FIND_CHARS;
find_trans = FIND_CAPS;
find_left_bound = 1;
find_right_bound = bp->maxlen;
for (ox = 0; ox < find_operand_count; ox++) {
op = find_operand[ox];
ff = find_qform[ox];
if (ff != FIND_UNQUOTED) {
if (find_string_given) finderror = TRUE;
else {
strcpy(find_string,op);
find_form = ff;
find_string_given = TRUE;
}
}
else {
copy_uppercase(temp,op);
if (EQUAL(temp,"*")) {
if (find_string_given) finderror = TRUE;
else {
strcpy(find_string,np->text_find_string);
find_form = ff;
find_string_given = TRUE;
}
}
else if (find_operand_count == 1) {
strcpy(find_string,op);
find_form = ff;
find_string_given = TRUE;
}
else if (EQUAL(temp,"NEXT")) {
if (find_what_given) finderror = TRUE;
else {
find_what = FIND_NEXT;
find_what_given = TRUE;
}
}
else if (EQUAL(temp,"PREV")) {
if (find_what_given) finderror = TRUE;
else {
find_what = FIND_PREV;
find_what_given = TRUE;
}
}
else if (EQUAL(temp,"FIRST")) {
if (find_what_given) finderror = TRUE;
else {
find_what = FIND_FIRST;
find_what_given = TRUE;
}
}
else if (EQUAL(temp,"LAST")) {
if (find_what_given) finderror = TRUE;
else {
find_what = FIND_LAST;
find_what_given = TRUE;
}
}
else if (EQUAL(temp,"ALL")) {
if (find_what_given) finderror = TRUE;
else {
find_what = FIND_ALL;
find_what_given = TRUE;
}
}
else if (EQUAL(temp,"CHARS")) {
if (find_type_given) finderror = TRUE;
else {
find_type = FIND_CHARS;
find_type_given = TRUE;
}
}
else if (EQUAL(temp,"WORD")) {
if (find_type_given) finderror = TRUE;
else {
find_type = FIND_WORD;
find_type_given = TRUE;
}
}
else if (EQUAL(temp,"PREFIX") || EQUAL(temp,"PRE")) {
if (find_type_given) finderror = TRUE;
else {
find_type = FIND_PREFIX;
find_type_given = TRUE;
}
}
else if (EQUAL(temp,"SUFFIX") || EQUAL(temp,"SUF")) {
if (find_type_given) finderror = TRUE;
else {
find_type = FIND_SUFFIX;
find_type_given = TRUE;
}
}
else if (*(temp+strspn(temp,"0123456789")) == '\0') {
if (find_left_bound_given) {
if (find_right_bound_given) finderror = TRUE;
else {
find_right_bound = atoi(temp);
if (find_right_bound > bp->maxlen) out_of_bounds = TRUE;
find_right_bound_given = TRUE;
}
}
else {
find_left_bound = atoi(temp);
if (find_right_bound < 1) out_of_bounds = TRUE;
find_left_bound_given = TRUE;
}
}
else {
if (find_string_given) finderror = TRUE;
else {
strcpy(find_string,op);
find_form = ff;
find_string_given = TRUE;
}
}
}
}
}
if (out_of_bounds) {
ERR2("Invalid bound; Bounds must lie between 1 and %d", bp->maxlen);
return FALSE;
}
if (finderror) {
ERR1("Put string in quotes; Conflicting or unknown parameter.");
return FALSE;
}
len = strlen(find_string);
if (find_string_given) bp->find_hit_end = FALSE;
if (find_left_bound_given && find_right_bound_given
&& find_left_bound > find_right_bound) {
n = find_left_bound;
find_left_bound = find_right_bound;
find_right_bound = n;
}
else if (find_left_bound_given && !find_right_bound_given) {
find_right_bound = find_left_bound + len - 1;
}
if (find_string_given) {
switch (find_form) {
case FIND_UNQUOTED: find_trans = FIND_CAPS; break;
case FIND_QUOTED: find_trans = FIND_CAPS; break;
case FIND_C: find_trans = FIND_ASIS; break;
case FIND_T: find_trans = FIND_CAPS; break;
case FIND_P: find_trans = FIND_GENERIC; break;
case FIND_X: find_trans = FIND_HEX;
if (len % 2 != 0) {
ERR1("Odd number of characters in hex string.");
return FALSE;
}
if (len != strspn(find_string,"0123456789abcdefABCDEF")) {
ERR1("Invalid (non-hex) characters in hex string.");
return FALSE;
}
for (p = find_string, q = find_string; *p; p += 2, *q++) {
sprintf(temp,"0x%2.2s",p);
sscanf(temp,"%x",&n);
*q = (char)n;
}
*q = '\0';
len = strlen(find_string);
break;
}
}
/* Store parameters for next Repeat Find operation. */
strcpy(np->text_find_string,find_string);
switch (find_what) {
case FIND_PREV:
case FIND_LAST: np->text_find_what = FIND_PREV; break;
default: np->text_find_what = FIND_NEXT; break;
}
np->text_find_type = find_type;
np->text_find_trans = find_trans;
np->text_find_left_bound = find_left_bound;
np->text_find_right_bound = find_right_bound;
if (!*find_string) {
ERR1("A null string is not allowed for the FIND command.");
return FALSE;
}
if (bp->total == 0) {
ERR1("There is no text to search.");
return FALSE;
}
strcpy(bp->zcmd,"");
switch (find_type) {
case FIND_CHARS: show_type = "Chars"; break;
case FIND_WORD: show_type = "Word"; break;
case FIND_PREFIX: show_type = "Prefix"; break;
case FIND_SUFFIX: show_type = "Suffix"; break;
default: show_type = "Text"; break;
}
switch (find_trans) {
case FIND_ASIS: strcpy(show_string+0,"C'");
strcpy(show_string+2,find_string);
strcat(show_string,"'");
break;
case FIND_GENERIC: strcpy(show_string+0,"P'");
strcpy(show_string+2,find_string);
strcat(show_string,"'");
break;
case FIND_HEX: strcpy(show_string+0,"X'");
for (p=find_string,q=show_string+2;*p;p++,q+=2) {
sprintf(q,"%2.2X",*p);
}
strcat(show_string,"'");
break;
case FIND_CAPS:
default: strcpy(show_string+0,"'");
strcpy(show_string+1,find_string);
strcat(show_string,"'");
break;
}
switch (find_trans) {
case FIND_CAPS:
uppercase_in_place(find_string);
break;
case FIND_GENERIC:
ERR1("The P'string' generic format is not supported.");
return FALSE;
}
hit_end = bp->find_hit_end;
findlen = strlen(find_string);
if (find_what == FIND_ALL) {
bp->find_count = 0;
if (!find_it(np,bp,find_string,findlen,
find_type,FIND_FIRST,find_trans,
find_left_bound, find_right_bound)) {
sprintf(shortmsg,"No %s %s found",show_type,show_string);
sprintf(longmsg,
"%s %s - not found within columns %d to %d",
show_type,show_string,find_left_bound,find_right_bound);
ERR3("%24s;%s",shortmsg,longmsg);
return FALSE;
}
bp->found_row = bp->find_row;
bp->found_col = bp->find_col;
bp->find_count = 1;
while (find_it(np,bp,find_string,findlen,
find_type,FIND_ALL,find_trans,
find_left_bound, find_right_bound)) {
bp->find_count++;
}
bp->find_hit_end = FALSE;
}
else {
if (!find_it(np,bp,find_string,findlen,
find_type,find_what,find_trans,
find_left_bound, find_right_bound)) {
if (hit_end) {
sprintf(shortmsg,"No %s %s found",show_type,show_string);
sprintf(longmsg,
"%s %s - not found within columns %d to %d",
show_type,show_string,find_left_bound,find_right_bound);
ERR3("%24s;%s",shortmsg,longmsg);
return FALSE;
}
else if (np->text_find_what == FIND_PREV) {
sprintf(shortmsg,"Top of data reached");
sprintf(longmsg,
"%s %s not found. Use RFIND to continue from bottom.",
show_type, show_string);
ERR3("%24s;%s",shortmsg,longmsg);
}
else {
sprintf(shortmsg,"Bottom of data reached");
sprintf(longmsg,
"%s %s not found. Use RFIND to continue from top.",
show_type, show_string);
ERR3("%24s;%s",shortmsg,longmsg);
}
return FALSE;
}
bp->found_row = bp->find_row;
bp->found_col = bp->find_col;
}
if (bp->found_row + 1 < bp->top
|| bp->found_row + 1 >= bp->top + bp->lvl - bp->cols) {
bp->top = bp->found_row + 1 - 1;
if (bp->top < 0) bp->top = 0;
}
if (bp->found_col < bp->coloff) {
bp->coloff = bp->found_col;
*bp->cols_line = '\0';
}
else if (bp->found_col+len > bp->coloff+80) {
bp->coloff = bp->found_col + len - 80;
if (bp->coloff < 0) bp->coloff = 0;
*bp->cols_line = '\0';
}
strcpy(bp->cursor, "NNBDYNA");
bp->csrpos = 80 * (bp->found_row - bp->top+bp->cols + 1)
+ bp->found_col - bp->coloff + 1;
bp->found_left = bp->csrpos;
bp->found_right = bp->found_left + len;
bp->reinit_browse = TRUE;
if (find_what == FIND_ALL) {
sprintf(shortmsg,"%d %s %s",bp->find_count,show_type,show_string);
sprintf(longmsg,
"%s %s found %d times within columns %d to %d",
show_type,show_string,bp->find_count,
find_left_bound,find_right_bound);
WARN3("%24s;%s",shortmsg,longmsg);
}
else {
sprintf(shortmsg,"%s %s found",show_type,show_string);
sprintf(longmsg,
"Search for %s %s within columns %d to %d was successful",
show_type,show_string, find_left_bound,find_right_bound);
WARN3("%24s;%s",shortmsg,longmsg);
}
bp->find_row = bp->found_row;
bp->find_col = bp->found_col;
return TRUE;
}
/************ Fill browse dynamic area. *******************************/
static void
fill_browse_dynamic_area(np,bp)
Rstruc nncb *np;
Rstruc browser *bp;
{
struct textline **tpp = NULL;
register char *cp = NULL;
register char *p;
char *q;
char *r;
int i;
int j;
char temp[12];
static char top_of_data_line[81] = "\
********************************* Top of data \
**********************************";
static char bottom_of_data_line[81] = "\
******************************** Bottom of data \
********************************";
bp->lastpos = bp->bda + bp->size;
bp->total = bp->thp->text_line_count;
memset(bp->bda,' ',bp->size);
if (bp->more_rows == -MAX_INT)
bp->top = 0;
else if (bp->more_rows == MAX_INT)
bp->top = bp->total + 2 - bp->lvl + bp->cols;
else bp->top += bp->more_rows;
if (bp->top < 0) bp->top = 0;
if (bp->top > bp->total) bp->top = bp->total + 1;
i = bp->top;
p = bp->bda;
if (bp->cols > 0) {
if (!*bp->cols_line) {
for (j=bp->coloff+1,r=bp->cols_line; j<=bp->coloff+80; j++,r++) {
if (j%10 == 0) {
sprintf(temp,"%d",j%100);
*r = temp[0];
}
else if (j%5 == 0) *r = '+';
else *r = '-';
}
}
memcpy(p,bp->cols_line,80);
p += 80;
}
if (i == 0) {
memcpy(p,top_of_data_line,80);
p += 80;
i++;
}
bp->firstpos = p;
for (tpp=&bp->tv[i-1];i<=bp->total && p<bp->lastpos;i++,tpp++,p+=80) {
if ((*tpp)->tab_expanded_text_length > bp->coloff) {
cp = (*tpp)->tab_expanded_text + bp->coloff;
for (j = 0, q = p; *cp && j < 80; j++, q++, cp++) {
if (*cp > 0xf9 || *cp < 0x40) *q = np->text_dispchar;
else *q = *cp;
}
}
}
if (p < bp->lastpos) {
memcpy(p,bottom_of_data_line,80);
}
return;
}
/************ Highlight browse text. **********************************/
static void
highlight_browse_text(np,bp)
Rstruc nncb *np;
Rstruc browser *bp;
{
char *p;
bp->highlighted = FALSE;
if (bp->found_left) {
if (EQUAL(bp->cursor,"NNBDYNA")) {
for (p = bp->bda + bp->found_left - 1; p >= bp->firstpos; p--) {
if (*p == ' ') {
*p = DATAOUT_HIGH;
bp->highlighted = TRUE;
break;
}
}
for (p = bp->bda + bp->found_right - 1; p <= bp->lastpos; p++) {
if (*p == ' ') {
*p = DATAOUT_LOW;
bp->highlighted = TRUE;
break;
}
}
}
}
bp->found_left = 0;
bp->found_right = 0;
return;
}
/************ Display browse data. ************************************/
static void
display_browse_data(np,bp,tdp)
Rstruc nncb *np;
Rstruc browser *bp;
Rstruc tabledesc *tdp;
{
Rstruc cmddesc *cdp;
char *cp;
char *operands;
int displayrc;
int zscrolln;
int leftcol;
int rightcol;
int command_index;
Bool command_processed_ok;
Bool is_max;
Bool is_scroll_word;
Bool is_scroll_cursor;
SCROLL scroll_amount;
char command [COMMANDSIZE+1];
char zverb [16];
char zscrolla [16];
char longmsg [73];
char nnbtitle [81];
char nnbmsg [81];
char temp1 [81];
char temp2 [81];
bp->more_rows = 0;
bp->override_scroll = FALSE;
bp->exit_browse = FALSE;
memset (nnbtitle, '-', 80);
strcpy (nnbtitle, "Browse - ");
memcpy (nnbtitle + 9, bp->title, strlen(bp->title));
if (!np->setmsg) {
leftcol = bp->coloff + 1;
rightcol = bp->coloff + 80;
if (bp->top > bp->total) strcpy(temp1,"");
else sprintf(temp1, " Line %d of %d,", bp->top, bp->total);
if (bp->maxlen <= 80)
sprintf(temp2," Cols %d-%d",leftcol,rightcol);
else sprintf(temp2," Cols %d-%d of %d",leftcol,rightcol,bp->maxlen);
strcpy(nnbmsg,temp1);
strcat(nnbmsg,temp2);
strcpy (nnbtitle + 79 - strlen(nnbmsg), nnbmsg);
}
(void)NNMivput(np,"NNBTITLE ",nnbtitle ,-1);
(void)NNMivput(np,"ZCMD " ,bp->zcmd ,-1);
(void)NNMivput(np,"NNBDYNA " ,bp->bda ,bp->size);
(void)NNMivput(np,"NNBCUR " ,bp->cursor ,-1);
sprintf(temp1,"%d",bp->csrpos);
(void)NNMivput(np,"NNBPOS " ,temp1 ,-1);
(void)NNMivput(np,"YRFIND " ,"ALIAS FIND",-1);
displayrc = NNMdispl(np,"NNMVIEW ");
if (displayrc > 0) bp->exit_browse = TRUE;
(void)NNMivput(np,"YRFIND " ,"",-1);
(void)NNMivget(np,"NNBCUR " ,bp->cursor , 8);
(void)NNMivget(np,"ZCMD " ,bp->zcmd ,sizeof(bp->zcmd));
bp->lvl = NNMiget(np,"NNBLVL ");
bp->csrpos = NNMiget(np,"NNBPOS ");
strip_trailing_in_place(bp->cursor); /* try to fix UCLA find bug */
strcpy(bp->find_cursor, bp->cursor);
bp->find_csrpos = bp->csrpos;
strcpy(bp->cursor,"");
bp->csrpos = 1;
if (bp->highlighted) bp->reinit_browse = TRUE;
else bp->reinit_browse = FALSE;
if (*bp->zcmd) {
memset(command,' ',COMMANDSIZE);
command_index = 0;
for (cp = bp->zcmd; *cp && !isspace(*cp); cp++) {
if (cp >= bp->zcmd+COMMANDSIZE) {
ERR1("Unknown command name.");
command_processed_ok = FALSE;
}
command[command_index++] = toupper(*cp);
}
while (*cp && isspace(*cp)) cp++;
for (cdp=tdp->first_cmddesc; *cdp->command_name != ' '; cdp++) {
if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
command_processed_ok = (cdp->command_processor)(np,bp,cp);
cdp = NULL;
break;
}
#define LASTAPCMD "OPT "
#define LASTAPLEN 4
else if (!bp->ap
&& !memcmp(cdp->command_name,LASTAPCMD,LASTAPLEN))
break;
}
if (cdp) {
for (cdp=tdp->next_cmddesc; *cdp->command_name != ' '; cdp++) {
if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
command_processed_ok = (cdp->command_processor)(np,bp,cp);
cdp = NULL;
break;
}
}
}
if (cdp) {
ERR1("Unknown command name.");
command_processed_ok = FALSE;
}
if (command_processed_ok) strcpy(bp->zcmd,"");
}
if (np->quit || bp->exit_browse) return;
/* Check scroll request (ZSCROLLA direction, ZSCROLLN number).
* Skip this if something was done by a command which causes
* its own pseudo-scrolling to happen (like LOCATE).
*/
if (!bp->override_scroll) {
zscrolln = 0;
(void)NNMivget(np,"ZVERB " , zverb ,sizeof(zverb));
(void)NNMivget(np,"ZSCROLLA " , zscrolla ,sizeof(zscrolla));
zscrolln = NNMiget(np,"ZSCROLLN ");
is_max = FALSE;
is_scroll_word = FALSE;
is_scroll_cursor = FALSE;
switch (zscrolla[0]) {
case 'P':
case 'H':
case 'D': is_scroll_word = TRUE;
break;
case 'C': is_scroll_word = TRUE;
is_scroll_cursor = TRUE;
break;
case 'M': is_max = TRUE;
break;
}
if (EQUAL(zverb,"DOWN")) scroll_amount = DOWN;
else if (EQUAL(zverb,"UP")) scroll_amount = UP;
else if (EQUAL(zverb,"LEFT")) scroll_amount = LEFT;
else if (EQUAL(zverb,"RIGHT")) scroll_amount = RIGHT;
else scroll_amount = NO_SCROLL;
switch (scroll_amount) {
case NO_SCROLL:
bp->more_rows = 0;
break;
case DOWN:
if (is_max) bp->more_rows = MAX_INT;
else if (is_scroll_word)
bp->more_rows = zscrolln - bp->cols;
else bp->more_rows = zscrolln;
bp->reinit_browse = TRUE;
break;
case UP:
if (is_max) bp->more_rows = -MAX_INT;
else if (is_scroll_cursor)
bp->more_rows = -zscrolln;
else if (is_scroll_word)
bp->more_rows = -zscrolln - bp->cols;
else bp->more_rows = -zscrolln;
bp->reinit_browse = TRUE;
break;
case LEFT:
if (is_max) bp->coloff = 0;
else bp->coloff -= zscrolln;
if (bp->coloff < 0) bp->coloff = 0;
*bp->cols_line = '\0';
bp->more_rows = 0;
bp->reinit_browse = TRUE;
break;
case RIGHT:
if (is_max) bp->coloff = bp->maxcoloff;
else bp->coloff += zscrolln;
if (bp->coloff > bp->maxcoloff) bp->coloff = bp->maxcoloff;
*bp->cols_line = '\0';
bp->more_rows = 0;
bp->reinit_browse = TRUE;
break;
}
}
return;
}
/*---*/
static struct cmddesc browse_commands[] = {
{"L ",process_locate_command },
{"LOC ",process_locate_command },
{"LOCATE ",process_locate_command },
{"F ",process_find_command },
{"FIND ",process_find_command },
{"RFIND ",process_find_command },
{"YRFIND ",process_find_command },
{"COL ",process_cols_command },
{"COLS ",process_cols_command },
{"RES ",process_reset_command },
{"RESET ",process_reset_command },
{"NOCOL ",process_reset_command },
{"NOCOLS ",process_reset_command },
{"DISP ",process_display_command },
{"DISPL ",process_display_command },
{"DISPLAY ",process_display_command },
{"EXT ",process_extract_command },
{"EXTR ",process_extract_command },
{"EXTRACT ",process_extract_command },
{"PRT ",process_print_command },
{"PRNT ",process_print_command },
{"PRINT ",process_print_command },
{"ROT13 ",process_rot13_command },
/* overrides general */ {"OPTIONS ",process_options_command },
/* overrides general */ {"OPT ",process_options_command },
/* overrides general */ {"HEADERS ",process_headers_command },
/* overrides general */ {"HEADER ",process_headers_command },
{"UNREAD ",process_unread_command },
{"REPLY ",process_reply_command },
{"FOLLOWUP ",process_followup_command },
{"NEXT ",process_next_command },
{"PREV ",process_prev_command },
{"NEXTU ",process_nextu_command },
{"NU ",process_nextu_command },
{"PREVU ",process_prevu_command },
{"PU ",process_prevu_command },
{"NEXTT ",process_nextt_command },
{"NT ",process_nextt_command },
{"PREVT ",process_prevt_command },
{"PT ",process_prevt_command },
{"NEXTS ",process_nextsubj_command },
{"NEXTSUBJ ",process_nextsubj_command },
{"NS ",process_nextsubj_command },
{"PREVS ",process_prevsubj_command },
{"PREVSUBJ ",process_prevsubj_command },
{"PS ",process_prevsubj_command },
{"FIRSTS ",process_firstsubj_command},
{"FIRSTSUBJ ",process_firstsubj_command},
{"FS ",process_firstsubj_command},
{"LASTS ",process_lastsubj_command },
{"LASTSUBJ ",process_lastsubj_command },
{"LS ",process_lastsubj_command },
{"NEWSUBJ ",process_newsubj_command },
{"SUBJECT ",process_subject_command },
{"SUBJ ",process_subject_command },
{" ",NULL}
};
/****** View text in full screen mode (BROWSE replacement) ***********/
void
NNMview(np,gp,ap,texthdrp,title)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Rstruc newsarticle *ap;
struct texthdr *texthdrp;
char *title;
{
Rstruc tabledesc *tdp;
struct textline *tp;
struct textline **tv;
struct textline **textvector;
struct browser *bp;
struct browser browserstruct;
GETMAIN(textvector, struct textline *,
texthdrp->text_line_count, "text vector");
if (!textvector) {
ERR1("Not enough memory to display text.");
return;
}
bp = &browserstruct;
memset(bp,0,sizeof(struct browser));
bp->gp = gp;
bp->ap = ap;
bp->thp = texthdrp;
bp->tv = textvector;
strcpy(bp->title,title);
bp->more_rows = -MAX_INT; /* set initial request to scroll up max */
bp->top = 0;
bp->find_row = -1;
bp->find_col = -1;
bp->csrpos = 1;
strcpy(bp->cursor,"");
bp->reinit_browse = TRUE;
/* Collect text line pointers, skipping suppressed lines. */
bp->maxlen = 0;
for (tp=texthdrp->first_text_line, tv=textvector; tp; tp=tp->next) {
if (tp->text_length >= 0) {
*(tv++) = tp;
if (bp->maxlen < tp->tab_expanded_text_length)
bp->maxlen = tp->tab_expanded_text_length;
}
}
bp->maxcoloff = bp->maxlen - 80;
if (bp->maxcoloff < 0) bp->maxcoloff = 0;
GETMAIN(bp->work, char *, bp->maxlen+1, "browse work string");
if (!bp->work) return;
(void)NNMispf(np,
"PQUERY PANEL(NNMVIEW) AREANAME(NNBDYNA) DEPTH(NNBDEPTH)");
if (np->ispfrc != 0) return;
bp->depth = NNMiget(np,"NNBDEPTH ");
bp->size = bp->depth * 80;
GETMAIN(bp->bda, char *, bp->size+1, "browse dynamic area");
if (!bp->bda) return;
if (!np->text_dispchar) np->text_dispchar = '.';
tdp = np->display_table_vector->text_display_table;
tdp->first_cmddesc = browse_commands;
for (;;) {
if (bp->reinit_browse) {
fill_browse_dynamic_area(np,bp);
highlight_browse_text(np,bp);
}
display_browse_data(np,bp,tdp);
if (np->quit || bp->exit_browse) break;
}
FREEMAIN(bp->work,"browse work string");
FREEMAIN(bp->bda,"browse dynamic area");
FREEMAIN(textvector, "text vector");
return;
}
./ ADD NAME=NNMVNG,SSI=01110006
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@VNG ")
#pragma csect(static,"NN$VNG ")
#include "nn.h"
struct ngdynarray {
struct newsgroup *newsgroup;
};
/****** Display newsgroups via ISPF dynamic area. ********************/
Bool
NNMvng(np)
Rstruc nncb *np;
{
Rstruc newsgroup *gp;
Rstruc ngdynarray *ndp;
struct ngdynarray *ngdynarray_address;
Rstruc tabledesc *tdp;
Rstruc seldesc *sdp;
Rstruc cmddesc *cdp;
char *cp;
int next_offset;
int command_index;
int newsgroup_count;
int display_total;
int dti;
int ngi;
int prc;
int nnglvl;
int depth;
int topgroup;
int bottomgroup;
int save_topgroup;
int last_group_located;
int last_group_selected;
int groupcursor;
int zscrolln;
int dynsize;
int framelength;
int findbump;
short name_length;
Bool is_max;
Bool selection_processed_ok;
Bool command_processed_ok;
Bool text_not_found;
char *rowp;
char *nngdyna;
char sel;
char tcmd [72];
char nnghead [81];
char nngline [81];
char nngcsr [12];
char command [COMMANDSIZE];
char zverb [9];
char zscrolla [9];
char rowmessage[81];
static char dashes[65] =
"----------------------------------------------------------------";
tdp = np->display_table_vector->newsgroup_display_table;
np->current_newsgroup = NULL;
np->newsgroup_selected = FALSE;
np->newsgroup_criterion_changed = TRUE;
np->newsgroup_order_changed = TRUE;
text_not_found = FALSE;
strcpy(np->newsgroup_only_string,"");
/* Determine how many TOTAL newsgroups we have. */
newsgroup_count = 0;
for (gp = np->first_newsgroup; gp; gp = gp->next) newsgroup_count++;
/* Allocate a block of "ngdynarray" newsgroup pointers, one element
* for each newsgroup that is currently displayed. This must be
* big enough to hold all known newsgroups at maximum.
*/
if (newsgroup_count == 0) {
ERR1(
"No newsgroups to display. Use L option to get list from server."
);
return FALSE;
}
GETMAIN(ngdynarray_address, struct ngdynarray,
newsgroup_count, "newsgroup dynamic array");
if (!ngdynarray_address) return FALSE;
/* Get depth of dynamic area (number of rows to display on screen) */
(void)NNMispf(np,
"PQUERY PANEL(NNMDNG) AREANAME(NNGDYNA) DEPTH(NNGDEPTH)");
if (np->ispfrc != 0) return FALSE;
depth = NNMiget(np,"NNGDEPTH ");
/* Get storage for ISPF dynamic area variable to be constructed. */
dynsize = 80*depth;
GETMAIN(nngdyna, char, dynsize+1, "NNGDYNA buffer");
if (!nngdyna) return FALSE;
memset(nngdyna,' ',dynsize);
topgroup = 0;
groupcursor = 0;
last_group_located = -1;
last_group_selected = -1;
strcpy(tcmd,"");
memset(nngline,' ',80);
nngline[ 0] = DATAOUT_HIGH;
nngline[ 1] = 'S';
nngline[ 2] = DATAOUT_LOW;
memcpy(&nngline[ 3],"select",6);
nngline[ 9] = DATAOUT_HIGH;
nngline[10] = 'A';
nngline[11] = DATAOUT_LOW;
memcpy(&nngline[12],"all", 3);
nngline[15] = DATAOUT_HIGH;
nngline[16] = 'R';
nngline[17] = DATAOUT_LOW;
memcpy(&nngline[18],"reg", 3);
nngline[21] = DATAOUT_HIGH;
nngline[22] = 'D';
nngline[23] = DATAOUT_LOW;
memcpy(&nngline[24],"dereg", 5);
nngline[29] = DATAOUT_HIGH;
nngline[30] = 'M';
nngline[31] = DATAOUT_LOW;
memcpy(&nngline[32],"mark", 4);
nngline[36] = DATAOUT_HIGH;
nngline[37] = 'U';
nngline[38] = DATAOUT_LOW;
memcpy(&nngline[39],"unmark",6);
nngline[48] = DATAOUT_HIGH;
strcpy(&nngline[49],"Unread Count Range");
/* The last line above may be variable some day if we have to vary
the width of the numbers... */
/* Loop displaying newsgroups until END or criterion changed. */
do {
/* If the newsgroup display criteria have changed, or this is the
first time through, build the array of newsgroup pointers. */
if (np->newsgroup_criterion_changed || np->newsgroup_order_changed) {
ndp = ngdynarray_address;
display_total = 0;
topgroup = 0;
switch (np->newsgroup_order) {
case NNTP_LIST_ORDER:
gp = np->first_newsgroup_alt;
next_offset = (char *)&gp->next2 - (char *)gp;
break;
case ALPHABETICAL_ORDER:
default:
gp = np->first_newsgroup;
next_offset = (char *)&gp->next - (char *)gp;
break;
}
for (; gp; gp = *(struct newsgroup **)((int)gp + next_offset)) {
if (np->newsgroup_criterion_changed) {
OffGroupInTable(gp); /* guilty until proven innocent */
if ((np->show_all_newsgroups && !NoSuchGroup(gp))
|| gp->registered) {
if (!*np->newsgroup_only_string
|| strstr(gp->name,np->newsgroup_only_string)) {
SetGroupInTable(gp);
}
}
}
if (GroupInTable(gp)) {
display_total++;
ndp->newsgroup = gp;
ndp++;
}
}
}
np->newsgroup_criterion_changed = FALSE;
np->newsgroup_order_changed = FALSE;
/* Fill dynamic area with data for groups satisfying criterion. */
memset(nngdyna, ' ', dynsize);
for (dti = 0, ngi = topgroup, rowp = nngdyna;
dti < depth && ngi < display_total;
dti++, ngi++, rowp += 80) {
ndp = &ngdynarray_address[ngi];
gp = ndp->newsgroup;
rowp[ 0] = DATAIN_HIGH; /* selection code attribute */
rowp[ 1] = ' '; /* selection code field */
rowp[ 2] = gp->registered
? (gp->unread_count ? DATAOUT_YELLOW : DATAOUT_TURQ)
: (gp->unread_count ? DATAOUT_GREEN : DATAOUT_BLUE);
/* newsgroup name attribute */
memset(&rowp[3], '.', 40);
name_length = strlen(gp->name);
if (name_length > 40) name_length = 40;
memcpy(&rowp[3], gp->name, name_length);
rowp[3+name_length] = DATAOUT_BLUE;
rowp[43] = DATAOUT_PINK;
rowp[44] = gp->registered ? 'R' : ' ';
rowp[45] = DATAOUT_HIGH;
if (gp->unread_count != 0)
sprintf(&rowp[46], " %7d", gp->unread_count);
rowp[55] = DATAOUT_LOW;
if (gp->article_count == 0)
strcpy(&rowp[56]," 0 ");
else
sprintf(&rowp[56], "%7d %7d -%7d",
gp->article_count, gp->low_number, gp->high_number);
rowp[strlen(rowp)] = ' ';
if (NoSuchGroup(gp)) {
memcpy(&rowp[46],"******* No such newsgroup *******",33);
}
}
if (rowp < nngdyna + dynsize) {
rowp[0] = DATAOUT_HIGH;
memset(&rowp[1], '-',79);
}
bottomgroup = ngi - 1;
if (topgroup > bottomgroup) strcpy(rowmessage,"");
else sprintf(rowmessage, "%d-%d of %d",
topgroup + 1, bottomgroup + 1, display_total);
framelength = (79 - strlen(rowmessage) - sizeof("Newsgroup Listing")
- 3) / 2;
sprintf(nnghead, "%*.*s Newsgroup Listing %*.*s %s",
framelength, framelength, dashes,
framelength, framelength, dashes,
rowmessage);
if (last_group_selected >= 0 && np->newsgroup_autocursor) {
groupcursor = (last_group_selected - topgroup) * 80 + 2;
}
if (groupcursor > 0) {
sprintf(nngcsr,"%d",groupcursor);
(void)NNMivput(np,"NNGCSR ", nngcsr, -1);
}
else {
(void)NNMivput(np,"NNGCSR ", "0", 1);
}
(void)NNMivput(np,"NNGCMD ", tcmd, -1);
(void)NNMivput(np,"NNGHEAD ", nnghead, -1);
(void)NNMivput(np,"NNGLINE ", nngline, -1);
(void)NNMivput(np,"NNGDYNA ", nngdyna, dynsize);
(void)NNMivput(np,"YRFIND " , "ALIAS FIND",-1);
prc = NNMdispl(np,"NNMDNG ");
if (prc > 8) break;
/* (void)NNMispf(np,"VGET (ZVERB ZSCROLLA ZSCROLLN)"); */
(void)NNMivput(np,"YRFIND " ,"",-1);
(void)NNMivget(np,"NNGDYNA " , nngdyna, dynsize);
(void)NNMivget(np,"ZVERB " , zverb, sizeof(zverb));
(void)NNMivget(np,"ZSCROLLA ", zscrolla, sizeof(zscrolla));
zscrolln = NNMiget(np,"ZSCROLLN ");
nnglvl = NNMiget(np,"NNGLVL ");
/* Initialize what may be set by selection/command processors. */
strcpy(np->nngroup,"");
last_group_selected = -1;
last_group_located = -1;
groupcursor = 0;
np->please_locate_group = FALSE;
np->please_find_group = FALSE;
/* Process selections. */
for (ngi = topgroup, rowp = nngdyna;
ngi <= bottomgroup && !np->quit;
ngi++, rowp += 80) {
ndp = &ngdynarray_address[ngi];
gp = ndp->newsgroup;
sel = toupper(rowp[1]);
if (sel == ' ') continue;
for (sdp = tdp->first_seldesc; sdp->selection_code != ' '; sdp++) {
if (sel == sdp->selection_code) {
(void)NNMivput(np,"NNGNAME ",gp->name, -1);
selection_processed_ok = (sdp->selection_processor)(np,gp);
sdp = NULL;
break;
}
}
if (sdp) {
ERR1("Unknown selection code. Type one of the listed codes.");
selection_processed_ok = FALSE;
}
else if (selection_processed_ok) {
if (*np->nngroup) last_group_located = ngi;
if (np->newsgroup_autocursor) last_group_selected = ngi;
}
}
if (np->quit) break;
/* Process command if any. */
strcpy(tcmd,"");
(void)NNMivget(np,tdp->command_variable,tcmd,sizeof(tcmd));
if (strcmp(tcmd,"") != 0) {
memset(command,' ',COMMANDSIZE);
command_index = 0;
for (cp = tcmd; *cp && !isspace(*cp); cp++) {
if (cp >= tcmd+COMMANDSIZE) {
ERR1("Unknown command name.");
command_processed_ok = FALSE;
}
command[command_index++] = toupper(*cp);
}
while (*cp && isspace(*cp)) cp++;
for (cdp=tdp->first_cmddesc; cdp->command_name[0] != ' '; cdp++) {
if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
command_processed_ok = (cdp->command_processor)(np,NULL,cp);
cdp = NULL;
break;
}
}
if (cdp) {
for (cdp=tdp->next_cmddesc; cdp->command_name[0] != ' '; cdp++) {
if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
command_processed_ok = (cdp->command_processor)(np,NULL,cp);
cdp = NULL;
break;
}
}
}
if (cdp) {
ERR1("Unknown command name.");
command_processed_ok = FALSE;
}
if (command_processed_ok) strcpy(tcmd,"");
}
if (np->quit) break;
/* If locate to a specific group name was requested,
process before any scroll request. */
if (last_group_located >= 0 && np->newsgroup_autoscroll) {
text_not_found = FALSE;
topgroup = last_group_located;
}
else if (np->please_locate_group) {
text_not_found = FALSE;
for (topgroup = 0, ndp = ngdynarray_address;
topgroup < display_total;
topgroup++, ndp++) {
gp = ndp->newsgroup;
if (strcmp(gp->name,np->newsgroup_locate_string) >= 0) break;
}
if (topgroup == display_total) topgroup--;
}
else if (np->please_find_group) {
save_topgroup = topgroup;
switch (np->newsgroup_find_option) {
case FIND_NEXT:
findbump = 1;
if (np->repeat_find) {
if (text_not_found) topgroup = 0;
else topgroup++;
}
break;
case FIND_PREV:
findbump = -1;
if (np->repeat_find) {
if (text_not_found) topgroup = bottomgroup;
else topgroup--;
}
break;
case FIND_FIRST:
topgroup = 0;
findbump = 1;
break;
case FIND_LAST:
topgroup = display_total - 1;
findbump = -1;
break;
}
gp = NULL;
for (ndp = &ngdynarray_address[topgroup];
topgroup < display_total && topgroup >= 0;
topgroup += findbump, ndp += findbump) {
if (GroupInTable(ndp->newsgroup)
&& strstr(ndp->newsgroup->name,np->newsgroup_find_string)) {
gp = ndp->newsgroup;
break;
}
}
if (!gp) {
topgroup = save_topgroup;
text_not_found = TRUE;
ERR3("No %s newsgroups with '%s' in name.",
(findbump > 0 ? "more" : "previous"),
np->newsgroup_find_string);
}
else {
text_not_found = FALSE;
WARN1("Newsgroup found;\
The newsgroup whose name contains the desired text tops the display.");
}
}
else text_not_found = FALSE;
/* Process scroll request if any. */
is_max = EQUAL(zscrolla,"MAX");
if (EQUAL(zverb,"DOWN")) {
if (is_max) topgroup = display_total - nnglvl + 1;
else topgroup += zscrolln;
}
else if (EQUAL(zverb,"UP")) {
if (is_max) topgroup = 0;
else topgroup -= zscrolln;
}
if (topgroup < 0)
topgroup = 0;
if (topgroup > display_total)
topgroup = display_total;
} while (prc == 0);
FREEMAIN(nngdyna,"NNGDYNA buffer");
FREEMAIN(ngdynarray_address,"newsgroup dynamic area");
return TRUE;
}
./ ADD NAME=NNMVTX,SSI=01030005
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@VTX ")
#pragma csect(static,"NN$VTX ")
#include "nn.h"
/****** View the lines of text retrieved from the server. ************/
void
NNMvtx(np,gp,ap)
Rstruc nncb *np;
Rstruc newsgroup *gp;
Rstruc newsarticle *ap;
{
struct texthdr *texthdrp;
char title [81];
/* If article is not specified, use main nncb, else article's text */
texthdrp = (ap ? &ap->thdr : &np->thdr);
if (np->batch_mode) {
NNMbtext(np,texthdrp,NULL);
return;
}
if (ap) sprintf(title, "%s:%d ", gp->name, ap->number);
else sprintf(title, "NewsServer:%s ",np->nnserver);
NNMview(np,gp,ap,texthdrp,title);
return;
}
./ ADD NAME=NNMXARTT,SSI=01090002
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@XARTT")
#pragma csect(static,"NN$XARTT")
#include "nn.h"
#define FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
/****** Emit an article title. ***************************************/
static Bool
emit_title(np,vp,xfp)
Rstruc nncb *np;
VARK *vp;
FILE *xfp;
{
Rstruc newsarticle *ap = VARK2PARTICLE(*vp);
char *stat;
if IsMissing(*vp) stat = "Missing";
else if IsUnread(*vp) stat = "Unread";
else if IsRead(*vp) stat = "Read";
else stat = "?";
if (np->article_rows == 1) {
fprintf(xfp,"%7d %-51.51s %-8.8s %11.11s\n",
ap->number, ap->subject, stat, ap->date);
}
else {
fprintf(xfp,"%7d %-51.51s %-8.8s\n",
ap->number, ap->subject, stat);
}
if (np->article_rows >= 2) {
fprintf(xfp," %-51.51s %11.11s\n", ap->from, ap->date);
}
if (np->article_rows >= 3) {
fprintf(xfp," %-51.51s\n", ap->message_id);
}
if (ferror(xfp)) return FALSE;
else return TRUE;
}
/****** Extract article titles. **************************************/
Bool
NNMxartt(np,gp,mode)
Rstruc nncb *np;
Rstruc newsgroup *gp;
enum data_set_type mode;
{
FILE *xfp;
int count;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
VARK **wp;
VARK **wpfirst;
VARK **wplast;
struct extraction *ep;
struct extraction the_extraction;
if (!gp->article_vector) {
ERR2("Newsgroup %s contains no articles.",gp->name);
return FALSE;
}
/* Display panel asking for data set name into which to extract. */
ep = &the_extraction;
memset(ep,0,sizeof(struct extraction));
ep->mode = mode;
if (ep->mode == JES)
strcpy(ep->panelname,"NNMPPRN1");
else strcpy(ep->panelname,"NNMPEXN1");
if (!((xfp=NNMgetds(np,ep)))) return TRUE;
/* If append mode, and a separator line was specified, use it. */
if (ep->appending && *ep->separator) {
fprintf(xfp,"%s\n",ep->separator);
if (ep->blanking) fprintf(xfp,"\n");
}
fprintf(xfp," Newsgroup: %-43.43s Status Date\n\n", gp->name);
count = NNMrart(np,gp,FALSE,FALSE); /* Retrieve article titles */
if (gp->sort_vector) {
wpfirst = gp->sort_vector;
wplast = gp->sort_vector + gp->sort_count - 1;
for (wp = wpfirst; wp <= wplast; wp++) {
if (IsEligible(**wp)) {
if (!emit_title(np,*wp,xfp)) break;
}
}
#ifdef FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
np->top_sorted_article = gp->sort_vector;
#endif
}
else {
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
if (IsEligible(*vp)) {
if (!emit_title(np,vp,xfp)) break;
}
}
#ifdef FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
np->top_article = gp->vector_first;
#endif
}
fprintf(xfp,"\n");
if (ferror(xfp)) {
ERR2("An output error occurred writing to %s.", ep->dsname);
}
else {
WARN2("A list of titles has been written to %s.", ep->dsname);
}
(ep->closer)(np,ep,xfp,TRUE); /* Close the file */
return TRUE;
}
./ ADD NAME=NNMXARTX,SSI=01120005
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@XARTX")
#pragma csect(static,"NN$XARTX")
#include "nn.h"
/****** Extract an article. ******************************************/
static Bool
extract_it(np,gp,ep,vp,xfpp,newtopp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
struct extraction *ep;
VARK *vp;
FILE **xfpp;
int *newtopp;
{
struct newsarticle *ap;
char *cp1;
char *cp2;
int anum;
char pdspec [32];
if (np->extract_write_error || np->extract_close_error) return FALSE;
anum = VARK2NUMBER(gp,vp);
if (anum > ep->to_article_number) return FALSE;
if (anum < ep->from_article_number) return TRUE;
if (!(NNMcar(np,gp,anum,vp,&ap,NULL,RETRIEVE))) return TRUE;
if (ep->mode == PDS) {
sprintf(ep->member,"%8.8d",anum);
for (cp1 = ep->member, cp2 = ep->member_prefix;
*cp1 == '0' && *cp2;
cp1++, cp2++) {
*cp1 = *cp2;
}
(void)NNMivput(np,"NNEXMEM ",ep->member,-1);
sprintf(pdspec,"dd:%s(%s)",ep->ddname,ep->member);
}
else {
(void)NNMivput(np,"NNEXMEM "," ",-1);
}
if (*newtopp == 0) *newtopp = anum;
if (!NNMpick(np,ap)) { /* Pick article to process */
fprintf(stderr,"\n*** Error accessing article %d\n",ap->number);
return TRUE;
}
if (ep->mode == PDS) {
(*xfpp) = OPEN_TEXT_FILE_FOR_WRITE(pdspec);
if (!(*xfpp)) {
perror(pdspec);
ERR3("Cannot open member %s of PDS %s.", ep->member, ep->dsname);
return FALSE;
}
}
np->extract_file = (*xfpp);
np->extractionp = ep;
NNMdoit(np,ap, ep->mode==JES ? 'P' : 'E'); /* Process article picked*/
if (np->extract_write_error || np->extract_close_error) {
/*
* if (ep->mode == PDS) {
* if (fclose((*xfpp)) < 0) {
* /* perror(ep->dsname); */
/* ERR2("An error occurred closing data set %s.", ep->dsname);
* np->extract_close_error = TRUE;
* }
* }
*/
*newtopp = ap->number;
return FALSE;
}
/* If not appending (always true for PDS), close was done in NNMxtx.*/
if (ep->mode == SEQ) {
if (!ep->appending) {
(ep->closer)(np,ep,*xfpp,FALSE); /* Close the file */
if (np->extract_close_error) {
*newtopp = ap->number;
return FALSE;
}
(*xfpp) = OPEN_TEXT_FILE_FOR_APPEND(ep->dsname);
if (!(*xfpp)) {
perror(ep->dsname);
ERR2("Unable to open file %s.", ep->dsname);
np->extract_write_error = TRUE;
*newtopp = ap->number;
return FALSE;
}
ep->appending = TRUE;
}
}
return TRUE;
}
/****** Extract article text. ****************************************/
Bool
NNMxartx(np,gp,mode)
Rstruc nncb *np;
Rstruc newsgroup *gp;
enum data_set_type mode;
{
Rstruc newsarticle *ap;
FILE *xfp;
struct extraction *ep;
VARK *vp;
VARK *vpfirst;
VARK *vplast;
VARK **wp;
VARK **wpfirst;
VARK **wplast;
int new_top_article = 0;
struct extraction the_extraction;
if (!gp->article_vector) {
ERR2("Newsgroup %s contains no articles.",gp->name);
return FALSE;
}
/* Display panel asking for data set name into which to extract. */
ep = &the_extraction;
memset(ep,0,sizeof(struct extraction));
ep->mode = mode;
ep->article_count = gp->article_count;
switch (ep->mode) {
case PDS: strcpy(ep->panelname,"NNMPEXNP"); break;
case JES: strcpy(ep->panelname,"NNMPPRNS"); break;
case SEQ: strcpy(ep->panelname,"NNMPEXNS"); break;
}
if (!((xfp=NNMgetds(np,ep)))) return TRUE;
np->extract_tab_expanding = ep->tab_expanding;
np->extract_appending = ep->mode == PDS ? FALSE : TRUE;
np->extract_ejecting = ep->ejecting;
np->extract_blank_before_separator = ep->blanking;
np->extract_separator_line = ep->separator;
np->extract_write_error = FALSE;
np->extract_close_error = FALSE;
/* for each article (subject to range option), write */
if (gp->sort_vector) {
wpfirst = gp->sort_vector;
wplast = gp->sort_vector + gp->sort_count - 1;
for (wp = wpfirst; wp <= wplast; wp++) {
if (!extract_it(np,gp,ep,*wp,&xfp,&new_top_article)) break;
}
}
else {
vpfirst = &GETVARKFIRST(gp);
vplast = &GETVARKLAST(gp);
for (vp = vpfirst; vp <= vplast; vp++) {
if (!extract_it(np,gp,ep,vp,&xfp,&new_top_article)) break;
}
}
if (np->extract_write_error || np->extract_close_error)
np->top_article = new_top_article;
else if (new_top_article)
np->top_article = new_top_article;
if (xfp) {
if (np->extract_write_error) {
ERR2("An error occurred writing to %s.", ep->dsname);
}
else if (np->extract_close_error) {
if (ep->mode == PDS) {
ERR3("Cannot store member %s in %s. Check directory space.",
ep->member, ep->dsname);
}
else ERR2("An error occurred closing %s.", ep->dsname);
}
else {
WARN3("Articles from %s have been written to %s.",
gp->name, ep->dsname);
}
}
(ep->closer)(np,ep,xfp,TRUE); /* "Close" the PDS or the file */
return TRUE;
}
./ ADD NAME=NNMXLIST,SSI=01050026
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@XLIST")
#pragma csect(static,"NN$XLIST")
#include "nn.h"
/****** Extract newsgroup listing. ***********************************/
static void
output_newsgroup_line(np,gp,xfp)
Rstruc nncb *np;
Rstruc newsgroup *gp;
FILE *xfp;
{
char temp [81];
if (gp->article_count == 0) strcpy(temp,"");
else sprintf(temp,"%7d - %7d", gp->low_number, gp->high_number);
fprintf(xfp,"%*.*s %*.*s %c %7d %7d %s\n",
strlen(gp->name),
39,
gp->name,
39-strlen(gp->name),
39-strlen(gp->name),
".........................................",
(gp->registered ? 'R' : ' '),
gp->unread_count,
gp->article_count,
temp);
return;
}
/****** Extract newsgroup listing. ***********************************/
Bool
NNMxlist(np,mode)
Rstruc nncb *np;
enum data_set_type mode;
{
Rstruc newsgroup *gp;
FILE *xfp;
struct extraction *ep;
char temp [72];
struct extraction the_extraction;
/* Display panel asking for data set name into which to extract. */
ep = &the_extraction;
memset(ep,0,sizeof(struct extraction));
ep->mode = mode;
if (ep->mode == JES)
strcpy(ep->panelname, "NNMPPRNG");
else strcpy(ep->panelname, "NNMPEXNG");
if (!((xfp=NNMgetds(np,ep)))) return TRUE;
/* If append mode, and a separator line was specified, use it. */
if (ep->appending && *ep->separator) {
fprintf(xfp,"%s\n",ep->separator);
if (ep->blanking) fprintf(xfp,"\n");
}
fprintf(xfp,"\
Newsgroup Listing Unread Count \
Range\n\n");
switch (np->newsgroup_order) {
case NNTP_LIST_ORDER:
for (gp = np->first_newsgroup_alt; gp; gp = gp->next2) {
if (GroupInTable(gp)) {
output_newsgroup_line(np,gp,xfp);
}
}
break;
case NEWSRC_ORDER: /* not implemented - fall through */
case ALPHABETICAL_ORDER:
default: /* default is alphabetical order */
for (gp = np->first_newsgroup; gp; gp = gp->next) {
if (GroupInTable(gp)) {
output_newsgroup_line(np,gp,xfp);
}
}
break;
}
fprintf(xfp,"\n");
if (ferror(xfp)){
ERR2("An error occurred writing to %s.", ep->dsname);
}
else {
WARN2("A list of titles has been written to %s.", ep->dsname);
}
(ep->closer)(np,ep,xfp,TRUE); /* Close the file */
return TRUE;
}
./ ADD NAME=NNMXTX,SSI=010E0043
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
#pragma csect(code, "NN@XTX ")
#pragma csect(static,"NN$XTX ")
#include "nn.h"
#define XFPUTC(A) np->extract_write_error = (fputc((A),xfp) == EOF)
#define XFWRITE(A,B) fwrite((A),(B),1,xfp), \
np->extract_write_error = (ferror(xfp) != 0)
/****** Extract the lines of server text into a data set. ************/
Bool
NNMxtx(np,ap,headerstoo)
Rstruc nncb *np;
Rstruc newsarticle *ap;
Fool headerstoo;
{
FILE *xfp;
struct texthdr *thp;
struct textline *tp;
struct extraction *ep;
int l;
int linelen;
char *cp;
Bool printing;
char formatted_number [11];
struct extraction the_extraction;
/* If article is not specified, use main nncb, else article's text */
thp = (ap ? &ap->thdr : &np->thdr);
printing = np->printing;
np->printing = FALSE;
/* Set article data for message. */
if (ap) {
sprintf(formatted_number,"%d",ap->number);
(void)NNMivput(np,"NNTNUM ", formatted_number, -1);
(void)NNMivput(np,"NNTSUBJ ", ap->subject, -1);
}
else {
(void)NNMivput(np,"NNTNUM ", "", -1);
(void)NNMivput(np,"NNTSUBJ ", "", -1);
}
if (np->extract_file) {
if (!np->following_up) {
(void)NNMispf(np,"CONTROL DISPLAY LOCK");
if (printing)
(void)NNMispf(np,"DISPLAY PANEL(NNMLPRN2)");
else
(void)NNMispf(np,"DISPLAY PANEL(NNMLEXN2)");
}
xfp = np->extract_file;
ep = np->extractionp;
}
else {
ep = &the_extraction;
memset(ep,0,sizeof(struct extraction));
if (printing) {
ep->mode = JES;
strcpy(ep->panelname,"NNMPPRDS");
}
else {
ep->mode = SEQ;
strcpy(ep->panelname,"NNMPEXDS");
}
if (!((xfp=NNMgetds(np,ep)))) return FALSE;
np->extract_tab_expanding = ep->tab_expanding;
np->extract_appending = ep->appending;
np->extract_ejecting = ep->ejecting;
np->extract_blank_before_separator = ep->blanking;
np->extract_separator_line = ep->separator;
}
/* If append mode, and a separator line was specified, use it. */
np->extract_write_error = FALSE;
np->extract_close_error = FALSE;
if (np->extract_ejecting) {
XFPUTC('\f');
}
if (np->extract_appending) {
XFPUTC('\n');
if (np->extract_separator_line && *np->extract_separator_line) {
XFWRITE(np->extract_separator_line,
strlen(np->extract_separator_line));
XFPUTC('\n');
if (np->extract_blank_before_separator) XFPUTC('\n');
}
}
if (headerstoo) tp = thp->first_text_line;
else if ((tp=thp->text_body_line)) tp = tp->next;
linelen = (printing ? 120 : 251);
for (; tp && !np->extract_write_error; tp = tp->next) {
if (tp->text_length == 0) {
if (np->following_up) XFPUTC('>');
XFPUTC('\n');
}
else if (tp->text_length > 0) {
if (np->extract_tab_expanding) {
cp = tp->tab_expanded_text;
l = tp->tab_expanded_text_length;
}
else {
cp = tp->text;
l = tp->text_length;
}
for (; l>0 && !np->extract_write_error; cp+=linelen, l-=linelen) {
if (np->following_up) XFPUTC('>');
XFWRITE(cp,(l > linelen ? linelen : l));
XFPUTC('\n');
}
}
}
if (!np->extract_write_error && ferror(xfp))
np->extract_write_error = TRUE;
if (!np->following_up) {
if (!np->extract_appending || !np->extract_file) {
(ep->closer)(np,ep,xfp,printing); /* Close the file */
if (np->extract_close_error) return FALSE;
}
}
if (!np->extract_file) {
if (np->extract_write_error) {
ERR2("An error occurred writing to %s.",ep->dsname);
np->extract_write_error = TRUE;
}
else if (ap) {
WARN3("Article %d has been written to %s.",ap->number,ep->dsname);
}
else {
WARN2("Displayed text has been written to %s.",ep->dsname);
}
}
if (np->extract_write_error) return FALSE;
else return TRUE;
}
./ ENDUP
?!
//CLIST EXEC NNLOAD,TRK1='4',TO='CLIST'
//SYSIN DD DATA,DLM='?!'
./ ADD NAME=NNMFIUCV,SSI=01010036
/* REXX. This exec scans the job pack queues for IUCVMULT and returns
* with an error code if IUCVMULT is already loaded under a
* different TCB. This can only happen under PIE MultiTSO or a
* similar product that makes multiple job step TCB's.
*/
trace off
signal on novalue
search_name = "IUCVMULT"
count = 0
foundtcb. = ""
current_tcb = getword24("21C")
current_job_step_tcb = getword24(current_tcb,"7C")
current_ascb = getword24("224")
current_asxb = getword31(current_ascb,"6C")
first_tcb = getword24(current_asxb,"4")
tcb = first_tcb
motherflag = 0
do forever
if motherflag = 0 then do
call process
daughter_tcb = getword24(tcb,"88")
if daughter_tcb \= "00000000" then do
tcb = daughter_tcb
iterate
end
end
motherflag = 0
sister_tcb = getword24(tcb, "80")
if sister_tcb \= "00000000" then do
tcb = sister_tcb
iterate
end
mother_tcb = getword24(tcb, "84")
if mother_tcb \= "00000000" then do
tcb = mother_tcb
motherflag = 1
iterate
end
leave
end
if count = 0 then return 0
problem = 0
do i = 1 to count
if foundtcb.i = current_job_step_tcb then do
/*
say search_name "is already loaded under current TCB at "foundtcb.i"."
*/
end
else do
/*
say search_name "is loaded under different TCB at "foundtcb.i"."
*/
problem = 1
end
end
if problem = 1 then return 1
else return 0
process:
jpq = getword31(tcb,"2C")
cde = jpq
do while cde \= "00000000"
cde_contents = storage(cde,32)
cde_name = substr(cde_contents,9,8)
cde_epa = substr(cde_contents,9,8)
if search_name = cde_name then do
count = count + 1
foundtcb.count = tcb
end
cde = getword31(cde,"0")
end
return
getword31: parse arg addr, offset
temp1 = x2d(addr)
if offset = "" then temp2 = 0
else temp2 = x2d(offset)
return c2x(storage(d2x(temp1+temp2),4))
getword24: parse arg addr, offset
temp1 = x2d(addr)
if offset = "" then temp2 = 0
else temp2 = x2d(offset)
return "00"c2x(storage(d2x(temp1+temp2+1),3))
./ ADD NAME=NNMMAIL,SSI=01030000
/* REXX */
/*********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/*********************************************************************/
/**********************************************************************/
/* */
/* Argument 1: mail data set */
/* Argument 2: recipient(s) */
/* */
/**********************************************************************/
trace off
address TSO
/* Tailor these to your installation requirements. */
local_userid = userid()
local_domain = "MVS"
local_origin = "mvs.draper.com"
local_smtp_node = "SMTPSRV"
parse arg maildsn to
if pos("@",to) = 0 then to = to"@"local_origin
else do
parse var to before "<" after ">" junk
if after <> "" then to = after
end
"ALLOC FI(NNMMAILI) SHR REU DA("maildsn")"
if rc \= 0 then return rc
"EXECIO * DISKR NNMMAILI (FINIS STEM IN.)"
if rc \= 0 then return rc
"newstack"
say "HELO" local_domain
queue "HELO" local_domain
say "MAIL FROM:<"local_userid"@"local_origin">"
queue "MAIL FROM:<"local_userid"@"local_origin">"
say "RCPT TO:<"to">"
queue "RCPT TO:<"to">"
queue "DATA"
do i = 1 to in.0
if left(in.i,1) = "." then queue "."in.i
else if in.i = "" then queue " "
else queue in.i
end
queue "."
queue "QUIT"
queue ""
"EXECIO * DISKW NNMMAILI (FINIS)"
if rc \= 0 then return rc
"delstack"
"FREE FI(NNMMAILI)"
"TRANSMIT" local_domain"."local_smtp_node,
"DATASET("maildsn") NOEPILOG NOLOG NOPROLOG"
return 0
/* The following function enquotes a string. */
quote:
parse arg string
ix = 1
do forever
ix = pos("'",string,ix)
if ix = 0 then return "'"string"'"
string = insert("'",string,ix)
ix=ix+2
end
./ ADD NAME=NNMVS,SSI=010D0000
/* REXX. Syntax: NNMVS (we'll do the rest) */
/*********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/*********************************************************************/
/* *** Customize the following lines for your installation. *** */
/* */
/* Note: If you wish to specify a different ISPF APPLID for */
/* NNMVS, you will have to use the SELECT service to invoke */
/* the load module. If so, uncomment the LIBDEF's for ISPLLIB */
/* and the SELECT call, and comment out the TSO CALL call. */
/* */
/* Note: If you choose a panel library that is in TSO users' */
/* default ISPF allocations, you can remove the LIBDEF call. */
/* */
nnmprefix = "NNMVS"
nnmpanelsuffix = "ISPPLIB"
nnmloadsuffix = "LOAD"
nnmlmod = "NNMMAIN"
nnmpanel = nnmprefix"."nnmpanelsuffix
nnmload = nnmprefix"."nnmloadsuffix
nnmappl = "ISR"
trace off
signal on novalue
libdeffed = 0
parse arg args
"ISPQRY"
if rc > 0 then do
parse source . . execname . execds .
if execds = "?" then
icmd = "%"execname args
else
icmd = "EX '"execds"("execname")'" quote(args)
call startispf "NEWAPPL("nnmappl") CMD("icmd")"
exit
end
signal on failure
signal on halt
testparm = "-"
if wordpos("TEST", translate(args)) > 0 then testparm = testparm || "t"
else ,
if wordpos("DEBUG",translate(args)) > 0 then testparm = testparm || "d"
else testparm = ""
if find_iucvmult() <> 0 then do
say,
"A TCP/IP socket application may be active elsewhere in your session."
say "Please terminate the other application before trying this one."
exit
end
call libdef
call nnm_dialog
cleanup:
if libdeffed then call unlibdef
exit
error:failure:halt:say "NNMVS: Severe lossage."
say "Statement:" sourceline(sigl)
exit
nnm_dialog:
address TSO "CALL" "'"nnmload"("nnmlmod")'" quote(testparm)
/*
* address ISPEXEC,
* "SELECT PGM("nnmlmod") PARM("quote(testparm)")",
* "NEWAPPL("nnmappl") PASSLIB"
*/
if rc \= 0 then say "Return code from" nnmlmod "program is" rc
return
libdef:
address ISPEXEC "LIBDEF ISPPLIB DATASET ID('"nnmpanel"')"
/*
* address ISPEXEC "LIBDEF ISPLLIB DATASET ID('"nnmload"')"
*/
libdeffed = 1
return
unlibdef:
/*
* address ISPEXEC "LIBDEF ISPLLIB DATASET"
*/
address ISPEXEC "LIBDEF ISPPLIB DATASET"
libdeffed = 0
return
/*
* The following function starts ISPF from READY mode.
* Beware: splitting the screen starts up an identical copy of the
* application, which may not be desirable.
*/
startispf: parse arg string
"ISPSTART" string
return
/* The following function enquotes a string. */
quote: parse arg string
ix = 1
do forever
ix = pos("'",string,ix)
if ix = 0 then return "'"string"'"
string = insert("'",string,ix)
ix=ix+2
end
find_iucvmult: procedure
call nnmfiucv
return result
./ ADD NAME=NNMVSC,SSI=01030012
PROC 0 TEST DEBUG BATCH +
SERVER() GROUP() NEWSRC() OPTION() REGISTERSTATUS()
/*********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/*********************************************************************/
/**********************************************************************/
/* */
/* This is the CLIST version of the NNMVS driver. You may wish to */
/* use this in place of the REXX version if: */
/* */
/* - you don't have REXX (huh???) */
/* - you don't have XPROC (you can probably get it from the same */
/* place you got NNMVS) */
/* - you are experiencing RACF/ACF2/other-security-system problems */
/* trying to define access to the NNTP authorization file with */
/* program pathing rules or the equivalent */
/* */
/* The disadvantages are: */
/* */
/* - You can use the CLIST from READY mode only implicitly. In other */
/* words, a user won't be able to type EXEC 'library.clist(NNMVS)' */
/* from READY mode - it must be in SYSPROC and executed by name. */
/* */
/* - You don't get the check for multiple TCP/IP applications. */
/* */
/* Of course, even if you don't have XPROC, you may still want to use */
/* the REXX exec instead - you just have to take out the XPROC call */
/* and forget about being able to pass parameters to the exec. That */
/* isn't such a great loss, since none of the params are required. */
/* */
/**********************************************************************/
/* *** Customize the following lines for your installation. *** */
/* */
/* Note: If you wish to specify a different ISPF APPLID for */
/* NNMVS, you will have to use the SELECT service to invoke */
/* the load module. If so, uncomment the LIBDEF's for ISPLLIB */
/* and the SELECT call, and comment out the TSO CALL call. */
/* */
/* Note: If you choose a panel library that is in TSO users' */
/* default ISPF allocations, you can remove the LIBDEF call. */
/* */
SET NNMCLIST = NNMVS /* name of this CLIST */
SET NNMPREFIX = NNMVS
SET NNMPANELSUFFIX = ISPPLIB
SET NNMLOADSUFFIX = LOAD
SET NNMLMOD = NNMMAIN
SET NNMPANEL = &STR(&NNMPREFIX..&NNMPANELSUFFIX)
SET NNMLOAD = &STR(&NNMPREFIX..&NNMLOADSUFFIX)
SET NNMAPPL = ISR
CONTROL NOCAPS
SET STACKED = N
SET LIBDEFFED = N
ISPQRY
IF &LASTCC > 0 THEN DO
SET ICMD = &NRSTR(&NNMCLIST &TEST &DEBUG &BATCH +
SERVER('&SERVER') GROUP('&GROUP') +
NEWSRC('&NEWSRC') OPTION('&OPTION') +
REGISTERSTATUS('®ISTERSTATUS'))
ISPSTART NEWAPPL(&NNMAPPL) CMD(&NRSTR(&ICMD))
EXIT
END
IF &NRSTR(&OPTION) ^= &STR() THEN DO
IF &LENGTH(&NRSTR(&OPTION)) ^= 1 +
| &SYSINDEX(&NRSTR(&OPTION),TDB) ^= 0 THEN DO
WRITE NNMVS: Invalid option, &NRSTR(&OPTION).
EXIT CODE(12)
END
IF &NRSTR(&SERVER) = &STR() THEN DO
WRITE NNMVS: SERVER required when OPTION specified.
EXIT CODE(12)
END
IF &NRSTR(&NEWSRC) = &STR() THEN DO
WRITE NNMVS: NEWSRC required when OPTION specified.
EXIT CODE(12)
END
IF &NRSTR(&OPTION) = G && &NRSTR(&GROUP) = &STR() THEN DO
WRITE NNMVS: GROUP required when OPTION(G) specified.
EXIT CODE(12)
END
IF &NRSTR(REGISTERSTATUS) = &STR() THEN SET REGISTERSTATUS = PROMPT
END
SET TESTPARM = &STR(-)
IF &TEST = TEST THEN SET TESTPARM = &STR(&TESTPARM.t)
IF &DEBUG = DEBUG THEN SET TESTPARM = &STR(&TESTPARM.d)
IF &BATCH = BATCH THEN SET TESTPARM = &STR(&TESTPARM.b)
ISPEXEC LIBDEF ISPPLIB DATASET ID('&NNMPANEL')
/* ISPEXEC LIBDEF ISPLLIB DATASET ID('&NNMLOAD')
SET LIBDEFFED = Y
IF &NRSTR(&SERVER) NE THEN DO
SET NNSERVER = &NRSTR(&SERVER)
ISPEXEC VPUT (NNSERVER)
END
IF &NRSTR(&GROUP) NE THEN DO
SET NNGROUPI = &NRSTR(&GROUP)
ISPEXEC VPUT (NNGROUPI)
END
IF &NRSTR(&NEWSRC) NE THEN DO
SET NNNEWSRF = &NRSTR(&NEWSRC)
ISPEXEC VPUT (NNNEWSRF)
END
SET VPUTVARS =
IF &NRSTR(&SERVER) ^= &STR() THEN DO
SET NNSERVER = &NRSTR(&SERVER)
SET VPUTVARS = &STR(&VPUTVARS NNSERVER)
END
IF &NRSTR(&GROUP) ^= &STR() | &NRSTR(&OPTION) = G THEN DO
SET NNGROUPI = &NRSTR(&GROUP)
SET VPUTVARS = &STR(&VPUTVARS NNGROUPI)
END
IF &NRSTR(&NEWSRC) ^= &STR() THEN DO
SET NNNEWSRF = &NRSTR(&NEWSRC)
SET L = &LENGTH(&NRSTR(&NEWSRC))
IF &SUBSTR(1,&NEWSRC) = &STR(') +
&& &SUBSTR(&L,&NEWSRC) = &STR(') THEN DO
SET NNNEWSRC = &SUBSTR(2:&L-1,&NRSTR(&NEWSRC))
END
ELSE SET NNNEWSRC = &NRSTR(&SYSPREF..&NEWSRC)
SET VPUTVARS = &STR(&VPUTVARS NNNEWSRF NNNEWSRC)
END
IF &NRSTR(®ISTERSTATUS) ^= &STR() THEN DO
SET NNREGNNG = &SUBSTR(1,&NRSTR(®ISTERSTATUS)
SET VPUTVARS = &STR(&VPUTVARS NNREGNNG)
END
IF &STR(VPUTVARS) ^= &STR() THEN DO
ISPEXEC VPUT (VPUTVARS) PROFILE
END
IF &NRSTR(&OPTION) ^= &STR() THEN DO
SET TESTPARM = &NRSTR(&TESTPARM.&OPTION)
END
CALL '&NNMLOAD(&NNMLMOD)' '&NRSTR(&TESTPARM)'
/*
/* address ISPEXEC,
/* ISPEXEC SELECT PGM(&NNMLMOD) PARM('&NRSTR(&TESTPARM)') +
/* NEWAPPL(&NNMAPPL) PASSLIB
/*
IF &LASTCC NE 0 THEN DO
WRITE Return code from &NNMLMOD program is &LASTCC
END
IF &LIBDEFFED = Y THEN DO
/* ISPEXEC LIBDEF ISPLLIB DATASET
ISPEXEC LIBDEF ISPPLIB DATASET
SET LIBDEFFED = N
END
EXIT
./ ADD NAME=NNMVSL,SSI=01030003
/* REXX. From Leonard D. Woren <ldw@mvsa.usc.edu>.
* Modified by SEB to remove MSGS file and other stuff...
*
*/
trace off
signal on failure
signal on novalue
"XPROC 0 DEBUG LIST NEW OLD"
if rc <> 0 then return rc
If debug = 'DEBUG' Then Trace I
If list = 'LIST' Then Trace C
Address ISPEXEC
nnmvs_command = "%NNMVSP" new old
panel_name = "NNL"
prof = "ISPPROF"
Address TSO "PIECHECK"
piecc = Rc
Select
When(piecc = 0) Then Nop /* not under pie */
When(piecc = 12) Then Nop /* no piecheck cmd ==> not under pie */
When(piecc = 241) Then Nop /* pie session 1 */
Otherwise prof = 'IS1PROF'
End /* select */
"CONTROL ERRORS RETURN"
"TBOPEN NNLIST WRITE LIBRARY("prof") SHARE"
If Rc > 8 then signal ispf_error
If Rc = 0 Then "TBTOP NNLIST"
Else Do
"TBCREATE NNLIST WRITE LIBRARY("prof") NAMES(SERVER NEWSRC)"
If Rc ^= 0 Then signal ispf_error
End
csr = ""
dispcc = 0
Do Forever
"TBQUERY NNLIST ROWNUM(ROWNUM)"
If Rc > 8 then signal ispf_error
If rownum = 0 Then Do
server = ""
newsrc = ""
"TBADD NNLIST"
If RC > 8 then signal ispf_error
csr = "CURSOR(SERVER) CSRROW(1)"
End
"TBTOP NNLIST"
If Rc > 8 then signal ispf_error
nnsel = ""
If dispcc = 4 Then "TBDISPL NNLIST"
Else "TBDISPL NNLIST PANEL("panel_name")" csr
dispcc = Rc
csr = ""
If dispcc = 8 Then Do
"TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
If Rc > 8 then signal ispf_error
return 0
End
If (dispcc ^= 0 & dispcc ^= 4) Then Do
Say "TBDISPL Rc =" dispcc
Say zerrsm
Say zerrlm
"TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
If Rc > 8 then signal ispf_error
return 16
End
If zcmd = "" Then Do /* look for line commands */
Upper nnsel
Select
When (nnsel = "" ) Then "TBPUT NNLIST"
When (nnsel = "D") Then Do
/*
"CONTROL DISPLAY SAVE"
"DISPLAY PANEL(NNLDEL)"
delcc = Rc
"CONTROL DISPLAY RESTORE"
if delcc > 8 then signal ispf_error
If delcc = 0 Then */ "TBDELETE NNLIST"
Iterate
End
When (nnsel = "I") Then Do
server = ""
newsrc = ""
"TBADD NNLIST"
if Rc > 8 then signal ispf_error
"TBQUERY NNLIST POSITION(NEWROW)"
if Rc > 8 then signal ispf_error
csr = "CURSOR(SERVER) CSRROW("newrow")"
Iterate
End
When (nnsel = "R") Then Do
"TBADD NNLIST"
if Rc > 8 then signal ispf_error
"TBQUERY NNLIST POSITION(NEWROW)"
if Rc > 8 then signal ispf_error
csr = "CURSOR(SERVER) CSRROW("newrow")"
Iterate
End
When (nnsel = "S") Then Do
"TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
cc = Rc
if cc > 8 then signal ispf_error
If cc ^= 0 Then Say "TBCLOSE rc =" cc
operands = ""
If server ^= "" Then operands = "SERVER("server")"
If newsrc ^= "" Then operands = operands "NEWSRC("newsrc")"
Address TSO nnmvs_command operands
return 0
End
Otherwise Do
badsel = nnsel
zerrsm = badsel "invalid"
zerrlm = badsel "is not a valid line command"
zerralrm = "YES"
zerrhm = "*"
"SETMSG MSG(ISRZ002)"
If Rc > 8 Then signal ispf_error
End
End /* select */
End /* zcmd = "" */
Else Do /* zcmd ^= "" */
badcmd = Word(zcmd,1)
zerrsm = "Invalid command"
zerrlm = badcmd "is not a valid primary command"
zerralrm = "YES"
zerrhm = "*"
"SETMSG MSG(ISRZ002)"
If Rc > 8 Then signal ispf_error
End /* zcmd ^= "" */
End /* main loop */
return 0
/* ISPF dialog error handling. */
ispf_error:
address ISPEXEC "DISPLAY PANEL(ISPTERM)"
signal cleanup
error:failure:halt:say "NNMVSL: Severe lossage."
say "Statement:" sourceline(sigl)
exit
./ ADD NAME=NNMVSP,SSI=010D0033
/* REXX. Syntax: NNMVS (see XPROC for the rest) */
/*********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/*********************************************************************/
/* *** Customize the following lines for your installation. *** */
/* */
/* If nnmpanel is set to "", it will not be LIBDEF'd. */
/* If nnmload is set to "", it will not be LIBDEF'd. */
/* */
save_prompt = prompt("ON")
"XPROC 0 TEST DEBUG FORCE NEW OLD BATCH BATCHIN(*) BATCHOUT(*)
SERVER() GROUP() NEWSRC() OPTION() REGISTERSTATUS()"
if rc <> 0 then exit rc
call prompt save_prompt
select
when new = "NEW" then do
nnmprefix = "NNMVS" /* or use "new" (testing) parameters */
nnmpanelsuffix = "ISPPLIB" /* or use "new" (testing) parameters */
nnmloadsuffix = "LOAD" /* or use "new" (testing) parameters */
nnmlmod = "NNMMAIN" /* or use "new" (testing) parameters */
end
when old = "OLD" then do
nnmprefix = "NNMVS" /* or use "old" (backup) parameters */
nnmpanelsuffix = "ISPPLIB" /* or use "old" (backup) parameters */
nnmloadsuffix = "LOAD" /* or use "old" (backup) parameters */
nnmlmod = "NNMMAIN" /* or use "old" (backup) parameters */
end
otherwise do
nnmprefix = "NNMVS"
nnmpanelsuffix = "ISPPLIB"
nnmloadsuffix = "LOAD"
nnmlmod = "NNMMAIN"
end
end
nnmpanel = nnmprefix"."nnmpanelsuffix
nnmload = nnmprefix"."nnmloadsuffix
nnmappl = "ISR"
batchhelp = "'"nnmprefix".HELP.TEXT'"
nnmvswizard = "Steve Bacher <seb@draper.com>" /* next of kin */
nnmvsmeister = "" /* TSOID of NNMVS's Big Brother */
trace off
signal on novalue
libdeffed = 0
if batch = "" then do
"ISPQRY"
if rc > 0 then do
parse arg args
parse source . . execname . execds .
if execds = "?" then
icmd = "%"execname args
else
icmd = "EX '"execds"("execname")'" quote(args)
call startispf "NEWAPPL("nnmappl") CMD("icmd")"
exit
end
end
signal on failure
signal on halt
if option <> "" then do
if length(option) <> 1 | pos(option,"TDB") <> 0 then do
say "NNMVS: Invalid option, "option"."
exit 12
end
if server = "" then do
say "NNMVS: SERVER is required when OPTION is specified."
exit 12
end
if newsrc = "" then do
say "NNMVS: NEWSRC is required when OPTION is specified."
exit 12
end
if option = "G" & group = "" then do
say "NNMVS: GROUP is required when OPTION(G) is specified."
exit 12
end
if registerstatus = "" then registerstatus = "PROMPT"
end
testparm = "-"
if test = "TEST" then testparm = testparm || "t"
if debug = "DEBUG" then testparm = testparm || "d"
if batch = "BATCH" then testparm = testparm || "b"
if find_iucvmult() <> 0 then do
say,
"A TCP/IP socket application may be active elsewhere in your session."
if force = "FORCE" then do
say "Proceeding anyhow, because you specified the FORCE keyword."
end
else do
say "Please terminate the other application before trying this one."
say "Or, if you are sure it's OK, try again with the FORCE keyword."
exit 8
end
end
if batch <> "" then call nnm_batch
else do
call libdef
call nnm_dialog
end
cleanup:
if libdeffed then call unlibdef
exit
error: say "NNMVS: Lossage has occurred."
say "Statement:" sourceline(sigl)
if nnmvswizard <> "" then say "Please notify" nnmvswizard"."
signal cleanup
failure: say "NNMVS: A failure has eventuated."
say "Statement:" sourceline(sigl)
if nnmvswizard <> "" then say "Please notify" nnmvswizard"."
signal cleanup
halt: say "NNMVS: A halt has been detected."
signal cleanup
nnm_dialog:
/* SERVER(*) --> (USC) Leonard Woren's server-table dialog */
if server = "*" | newsrc = "*" then do
nnmvsl_cmd = "%NNMVSL" new old
address ISPEXEC "SELECT CMD("nnmvsl_cmd") PASSLIB NEWAPPL("nnmappl")"
return
end
vputvars = ""
if server <> "" then do
nnserver = server
vputvars = vputvars "NNSERVER"
end
if group <> "" | option = "G" then do
nngroupi = group
vputvars = vputvars "NNGROUPI"
end
if newsrc <> "" then do
nnnewsrf = newsrc
if left(newsrc,1) = "'" then nnnewsrc = strip(newsrc,"B","'")
else nnnewsrc = sysvar("SYSPREF")"."newsrc
vputvars = vputvars "NNNEWSRF NNNEWSRC"
end
if registerstatus <> "" then do
nnregnng = left(registerstatus,1)
vputvars = vputvars "NNREGNNG"
end
if vputvars <> "" then do
address ISPEXEC "VPUT ("vputvars") PROFILE"
end
if option <> "" then do
testparm = testparm || option
end
call let_me_know
zerrmsg = ""
zerrsm = ""
zerrlm = ""
if nnmload = "" then do
address ISPEXEC "SELECT NEWAPPL("nnmappl") PASSLIB" ,
"PGM("nnmlmod") PARM("testparm")"
end
else do
command = "CALL '"nnmload"("nnmlmod")'" quote(testparm)
address ISPEXEC "SELECT NEWAPPL("nnmappl") PASSLIB CMD("command")"
end
if rc <> 0 then say "Return code from" nnmlmod "program is" rc
address ISPEXEC "VGET (ZERRSM ZERRLM)"
if zerrsm <> "" then do
say zerrmsg":" zerrsm
say zerrlm
end
return
nnm_batch:
if newsrc = "" then do
say "NNMVS: NEWSRC is required when BATCH is specified."
exit 12
end
if server <> "" ,
| group <> "" ,
| registerstatus <> "" ,
| option <> "" then do
say "NNMVS: SERVER, GROUP, OPTION, REGISTERSTATUS not valid",
"when BATCH is specified."
exit 12
end
address TSO "ALLOC FI(NNBATIN) DA("batchin") SHR REU"
if rc <> 0 then return
address TSO "ALLOC FI(NNBATOUT) DA("batchout") OLD REU"
if rc <> 0 then return
address TSO "ALLOC FI(NNBATHLP) DA("batchhelp") SHR REU"
if rc <> 0 then return
address TSO "ALLOC FI(NNNEWSRC) DA("newsrc") OLD REU"
if rc <> 0 then return
call let_me_know "BATCH"
address TSO "CALL '"nnmload"("nnmlmod")'" quote(testparm)
nrc = rc
address TSO "FREE FI(NNBATIN NNBATOUT NNBATHLP NNNEWSRC)"
if nrc <> 0 then say "Return code from" nnmlmod "program is" nrc
return
let_me_know:
if nnmvsmeister = "" | nnmvsmeister = userid() then return
parse arg letarg
parse source . . execname . execds .
call outtrap "X."
address TSO,
"SEND" quote(execds"("execname")" letarg date("U") time()" "),
"U("nnmvsmeister") LOGON"
call outtrap "OFF"
return
libdef:
if nnmpanel <> "" then do
address ISPEXEC "LIBDEF ISPPLIB DATASET ID('"nnmpanel"')"
if rc <> 0 then do; call ispf_error rc; exit rc; end
end
if nnmload <> "" then do
address ISPEXEC "LIBDEF ISPLLIB DATASET ID('"nnmload"')"
if rc <> 0 then do; call ispf_error rc; exit rc; end
end
libdeffed = 1
return
unlibdef:
if nnmload <> "" then do
address ISPEXEC "LIBDEF ISPLLIB DATASET"
if rc <> 0 then call ispf_error rc
end
if nnmpanel <> "" then do
address ISPEXEC "LIBDEF ISPPLIB DATASET"
if rc <> 0 then call ispf_error rc
end
libdeffed = 0
return
ispf_error: parse arg ispfrc
say "NNMVS: ISPF dialog service error detected..."
say
say zerrmsg":" zerrsm
say zerrlm
say
return ispfrc
/*
* The following function starts ISPF from READY mode.
* Beware: splitting the screen starts up an identical copy of the
* application, which may not be desirable.
*/
startispf: parse arg string
"ISPSTART" string
return
/* The following function enquotes a string. */
quote: parse arg string
ix = 1
do forever
ix = pos("'",string,ix)
if ix = 0 then return "'"string"'"
string = insert("'",string,ix)
ix=ix+2
end
/* The following function scans the job pack queues for IUCVMULT and
* returns with an error code if IUCVMULT is already loaded under a
* different TCB. This can only happen under PIE MultiTSO or a
* similar product that makes multiple job step TCB's.
*/
find_iucvmult: procedure
call nnmfiucv
return result
./ ENDUP
?!
//H EXEC NNLOAD,TRK1='6',TO='H'
//SYSIN DD DATA,DLM='?!'
./ ADD NAME=NN,SSI=01630044
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/* --------------------- "nn.h" include member --------------------- */
#pragma linkage(ispexec,OS)
#pragma linkage(isplink,OS)
#pragma linkage(ikjeff18,OS)
/****** Installation-customized defines. *****************************/
#include "nnuser.h"
#ifndef C370V1
#ifndef C370V2
#ifndef SASC
install_error_neither_C370V1_C370V2_nor_SASC_was_defined;
#endif
#endif
#endif
#ifndef TCPIPV1
#ifndef TCPIPV2
#ifndef SNSTCP
install_error_neither_TCPIPV1_nor_TCPIPV2_nor_SNSTCP_was_defined;
#endif
#endif
#endif
#ifndef ISPFV2
#ifndef ISPFV3
install_error_neither_ISPFV2_nor_ISPFV3_was_defined;
#endif
#endif
#define MVS
#ifdef C370V2
#pragma checkout(suspend)
#endif
/****** Clean up compiler warnings BEFORE time.h gets 'em ************/
#ifndef SASC
#define localtime LOCALTIM
#endif
/****** Include all header files that are necessary. *****************/
#include <manifest.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/uio.h>
#include <sys/ioctl.h>
/*
#include <tcperrno.h>
*/
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <time.h>
/*
#include <signal.h>
*/
#ifndef SASC
#include <ctest.h>
#endif
#ifdef SASC
#include "nnsasc.h"
#endif
/****** Version-dependent stuff **************************************/
#ifdef C370V1
#undef FETCH
#endif
#ifdef C370V2
#define FETCH
#endif
#ifdef TCPIPV1
#define TCP_DEBUG tcp_debug
#endif
#ifdef TCPIPV2
#define TCP_DEBUG sock_debug
#endif
#ifdef DEBUG
#define TCP_DEBUG_ON TCP_DEBUG(1)
#define TCP_DEBUG_OFF TCP_DEBUG(0)
#else
#define TCP_DEBUG_ON /* */
#define TCP_DEBUG_OFF /* */
#endif
#ifdef ISPFV3
#define ZERRLM_SIZE 513
#else
#define ZERRLM_SIZE 73
#endif
/****** Preprocessor bookkeeping *************************************/
#ifndef MAX
#define MAX(A,B) ((A) > (B) ? (A) : (B))
#endif
#ifndef MIN
#define MIN(A,B) ((A) < (B) ? (A) : (B))
#endif
#define Bool char
#define Fool unsigned int /* for function arguments */
#define COMMANDSIZE 12
#define READ_BYTES 1024
#define SERVER_BUF_MSGSIZE 1024
#define CLIENT_BUF_MSGSIZE 1024
#define TEXT_BYTES 1024
#define INTERNET_SIZE 256
#define GROUP_NAME_SIZE 255
#define NNTP_PORT_NUMBER 119
#define SOCKET_GETCHAR_ERROR (-1)
#define SOCKET_NO_MORE (-2)
#define SOCKET_READ_NOTHING (-3)
#define NO_NNTP_MESSAGE_NUM (-1)
#define NO_VALUE (-1)
#define PHONY_NEWS_ARTICLE (-1)
#define Rstruc register struct
#define EQUAL !strcmp
#define UNEQUAL strcmp
#define NEWSRC_ORDER 'N'
#define NNTP_LIST_ORDER 'L'
#define ALPHABETICAL_ORDER 'A'
#define FIND_NEXT 'N'
#define FIND_FIRST 'F'
#define FIND_LAST 'L'
#define FIND_PREV 'P'
#define FIND_ALL 'A'
#define FIND_CHARS '\0'
#define FIND_WORD 'W'
#define FIND_PREFIX 'P'
#define FIND_SUFFIX 'S'
#define FIND_CAPS '\0'
#define FIND_ASIS 'A'
#define FIND_HEX 'X'
#define FIND_GENERIC 'P'
#define FIND_BADFORM '\0'
#define FIND_UNQUOTED 'U'
#define FIND_QUOTED 'Q'
#define FIND_C 'C'
#define FIND_X 'X'
#define FIND_T 'T'
#define FIND_P 'P'
#define MAX_INT (int)0x7fffffff
#define LOCATE_INT (int)0x7ffffffe
#define SELECTION_ALL 'A'
#define SELECTION_REG 'R'
#define SELECTION_NNTP 'P'
#define SELECTION_GROUP 'G'
#define SELECTION_LIST 'L'
#define SELECTION_NEWG 'N'
#define SELECTION_OPTS 'O'
#define SELECTION_EXIT 'X'
#define SELECTION_LIST_DISCONNECT 'Z'
#define NO_ACTION '\0'
#define READ 'R'
#define RETRIEVED 'V'
#define EXTRACTED 'X'
#define PRINTED 'P'
#define UNREAD 'U'
#define MISSING 'M'
#define ERROR 'E'
#define CANCELLED 'C'
#define CARRIAGE_RETURN ('\r')
#ifdef MVS
#ifdef I370
#define LINE_FEED (0x15)
#else
#define LINE_FEED (0x25)
#endif
#else
#define LINE_FEED (0x0a)
#endif
#ifdef MVS
#ifdef SNSTCPIP
#define EtoA etoa
#define AtoE atoe
#else
#ifdef I370
#define EtoA htoncs
#define AtoE ntohcs
#else
#define EtoA(x) ebcdictoascii[x]
#define AtoE(x) asciitoebcdic[x]
#define ebcdictoascii ebcdicto
#define asciitoebcdic asciitoe
#endif
#endif
#endif
#ifdef SNSTCPIP
#define EBCDIC_TO_ASCII(A,B) EtoA(A,B)
#define ASCII_TO_EBCDIC(A,B) AtoE(A,B)
#else
#define EBCDIC_TO_ASCII(A,B) {int _i; \
for (_i=0; _i<(B); ++_i) \
(A)[_i] = EtoA((A)[_i]); \
}
#define ASCII_TO_EBCDIC(A,B) {int _i; \
for (_i=0; _i<(B); ++_i) \
(A)[_i] = AtoE((A)[_i]); \
}
#endif
#ifdef TCPIPV1
#define REPORT_TCP_ERROR(A) /* */
#endif
#ifdef TCPIPV2
#define REPORT_TCP_ERROR(A) tcperror(A)
#endif
#ifdef SNSTCPIP
#define REPORT_TCP_ERROR(A) fprintf(stderr,\
"\nTCP error on %s: errno = %d\n",\
A,GET_ERRNO)
#endif
#ifdef SNSTCPIP
#define Accept(A,B,C) accept((A),(struct sockaddr *)(B),(C))
#define Bind(A,B,C) bind((A),(struct sockaddr *)(B),(C))
#define Connect(A,B,C) connect((A),(struct sockaddr *)(B),(C))
#define Gethostbyaddr(A,B,C) gethostbyaddr((char *)(A),(B),(C))
#define Getpeername(A,B,C) getpeername((A),(struct sockaddr *)(B),(C))
#define Getsockopt(A,B,C,D) getsockopt((A),(B),(char *)(C),(D))
#define EWOULDBLOCK ESWOULDBLOCK
#define errno GET_ERRNO
#else
#define Accept accept
#define Bind bind
#define Connect connect
#define Gethostbyaddr gethostbyaddr
#define Getpeername getpeername
#define Getsockopt getsockopt
#endif
#ifdef FETCH
#define ISPLINK (np->isplink_pointer)
#define ISPEXEC (np->ispexec_pointer)
#else
#define ISPLINK isplink
#define ISPEXEC ispexec
#endif
#ifndef I370
#define WRITE_FILEMODE "w,recfm=vb,lrecl=259,blksize=6233"
#define APPEND_FILEMODE "a,recfm=vb,lrecl=259,blksize=6233"
#define SYSOUT_FILEMODE "w,recfm=vba,lrecl=133"
#define FILEMODE "recfm=vb,lrecl=259,blksize=6233"
#define FILEMODE_A "recfm=vba,lrecl=133"
#define OPEN_TEXT_FILE_FOR_WRITE(F) \
fopen((F),WRITE_FILEMODE)
#define OPEN_TEXT_FILE_FOR_APPEND(F) \
fopen((F),APPEND_FILEMODE)
#define OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B) \
fopen((F),(B) ? APPEND_FILEMODE : WRITE_FILEMODE)
#define OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B) \
fopen((F),(B) ? "a" : WRITE_FILEMODE)
#define OPEN_SYSOUT_FILE(F) \
fopen((F),SYSOUT_FILEMODE)
#define TEST_IF_FILE_EXISTS(P,F) (P=fopen((F),"r"))
#define CLEANUP_IF_FILE_EXISTS(P) (void)fclose(P)
#else
#define WRITE_FILEMODE "w,recfm=v,lrecl=255,blksize=6233"
#define APPEND_FILEMODE "a,recfm=v,lrecl=255,blksize=6233"
#define SYSOUT_FILEMODE "w,recfm=va,lrecl=133"
#define FILEMODE "recfm=v,lrecl=255,blksize=6233"
#define FILEMODE_A "recfm=va,lrecl=133"
#define OPEN_TEXT_FILE_FOR_WRITE(F) \
afopen((F),"w","seq",FILEMODE)
#define OPEN_TEXT_FILE_FOR_APPEND(F) \
afopen((F),"a","seq",FILEMODE)
#define OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B) \
afopen((F),(B)?"a":"w","seq",FILEMODE)
#define OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B) \
afopen((F),(B)?"a":"w","seq",FILEMODE)
#define OPEN_SYSOUT_FILE(F) \
afopen((F),"w","seq",FILEMODE_A)
#define TEST_IF_FILE_EXISTS(F,P) (access((F),0) == 0)
#define CLEANUP_IF_FILE_EXISTS(P) /* */
#endif
#define ebdtoasc(C) {char *__cp;\
for(__cp = C;*__cp;__cp++) *__cp = EtoA(*__cp);}
#define asctoebd(C) {char *__cp;\
for(__cp = C;*__cp;__cp++) *__cp = AtoE(*__cp);}
#define uppercase_in_place(C) {char *__cp;\
for(__cp=C;*__cp;__cp++) *__cp = toupper(*__cp);}
#define lowercase_in_place(C) {char *__cp;\
for(__cp=C;*__cp;__cp++) *__cp = tolower(*__cp);}
#define strip_trailing_in_place(C) {char *__cp;\
for(__cp=strchr((C),'\0');\
__cp>C && isspace(*(__cp-1)); __cp--);\
*__cp='\0';}
#define uppercase_and_strip_trailing_in_place(C) {char *__cp;\
for(__cp=C;*__cp;__cp++) *__cp = toupper(*__cp);\
for(; __cp>C && isspace(*(__cp-1)); __cp--);\
*__cp='\0';}
#define lowercase_and_strip_trailing_in_place(C) {char *__cp;\
for(__cp=C;*__cp;__cp++) *__cp = tolower(*__cp);\
for(; __cp>C && isspace(*(__cp-1)); __cp--);\
*__cp='\0';}
#define copy_uppercase(A,B) {char *__cA,*__cB;\
for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
*__cA = toupper(*__cB);\
*__cA='\0';}
#define copy_lowercase(A,B) {char *__cA,*__cB;\
for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
*__cA = tolower(*__cB);\
*__cA='\0';}
#define copy_uppercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
*__cA = toupper(*__cB);\
for (; __cA>A && isspace(*(__cA-1)); __cA--);\
*__cA='\0';C=__cA;}
#define copy_lowercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
*__cA = tolower(*__cB);\
for (; __cA>A && isspace(*(__cA-1)); __cA--);\
*__cA='\0';C=__cA;}
#define skip_whitespace(C) (C) + strspn((C)," \t")
#define skip_ISPF_whitespace(C) (C) + strspn((C)," ,\t")
#define find_whitespace(A,B) if (!(A=strpbrk((B)," \t")))\
A = strchr((B),'\0');
#define find_ISPF_whitespace(A,B) if (!(A=strpbrk((B)," ,\t")))\
A = strchr((B),'\0');
#define DATAOUT_LOW 0x01
#define DATAOUT_HIGH 0x02
#define DATAIN_LOW 0x03
#define DATAIN_HIGH 0x04
#define DATAOUT_BLUE DATAOUT_LOW
#define DATAOUT_GREEN 0x05
#define DATAOUT_PINK 0x06
#define DATAOUT_RED 0x07
#define DATAOUT_TURQ 0x08
#define DATAOUT_WHITE DATAOUT_HIGH
#define DATAOUT_YELLOW 0x09
#define DATAIN_BLUE 0x0a
#define DATAIN_GREEN DATAIN_LOW
#define DATAIN_PINK 0x0b
#define DATAIN_RED DATAIN_HIGH
#define DATAIN_TURQ 0x0c
#define DATAIN_WHITE 0x0d
#define DATAIN_YELLOW 0x0e
#define S99VRBAL 0x01 /* ALLOCATION */
#define S99VRBUN 0x02 /* UNALLOCATION */
#define S99VRBCC 0x03 /* CONCATENATION */
#define S99VRBDC 0x04 /* DECONCATENATION */
#define S99VRBRI 0x05 /* REMOVE IN-USE */
#define S99VRBDN 0x06 /* DDNAME ALLOCATION */
#define S99VRBIN 0x07 /* INFORMATION RETRIEVAL */
#define S99NOCNV 0x40 /* ALLOC FUNCTION-DO NOT USE AN */
/* EXISTING ALLOCATION TO SATISFY*/
/* THE REQUEST */
#define DALDDNAM 0x0001 /* DDNAME */
#define DALDSNAM 0x0002 /* DSNAME */
#define DALMEMBR 0x0003 /* MEMBER NAME */
#define DALSTATS 0x0004 /* DATA SET STATUS */
#define DALNDISP 0x0005 /* DATA SET DISPOSITION */
#define DALTRK 0x0007 /* TRACK SPACE TYPE */
#define DALBLKLN 0x0009 /* BLOCK LENGTH */
#define DALPRIME 0x000a /* PRIMARY SPACE ALLOCATION */
#define DALSECND 0x000b /* SECONDARY SPACE ALLOCATION */
#define DALDIR 0x000c /* DIRECTORY BLOCK ALLOCATION */
#define DALSYSOU 0x0018 /* SYSOUT */
#define DALSFMNO 0x001a /* SYSOUT FORMS NUMBER */
#define DALCOPYS 0x001d /* SYSOUT COPIES */
#define DALUCS 0x0029 /* UNIVERSAL CHARACTER SET */
#define DALBLKSZ 0x0030 /* DCB BLOCKSIZE */
#define DALDSORG 0x003c /* DATA SET ORGANIZATION */
#define DALLRECL 0x0042 /* DCB LOGICAL RECORD LENGTH */
#define DALRECFM 0x0049 /* DCB RECORD FORMAT */
#define DALPERMA 0x0052 /* PERMANENTLY ALLOCATED ATTRIB */
#define DALRTDDN 0x0055 /* RETURN DDNAME */
#define DALRTDSN 0x0056 /* RETURN DSNAME */
#define DALRTORG 0x0057 /* RETURN D.S. ORGANIZATION */
#define DALSUSER 0x0058 /* SYSOUT REMOTE WORKSTATION */
#define DUNDDNAM 0x0001 /* DDNAME */
#define DUNDSNAM 0x0002 /* DSNAME */
#define DUNUNALC 0x0007 /* UNALLOC OPTION */
#define SHR 0x08
#define NEW 0x04
#define MOD 0x02
#define OLD 0x01
#define KEEP 0x08
#define DELETE 0x04
#define CATLG 0x02
#define UNCATLG 0x01
#define RECFM_F 0x80
#define RECFM_V 0x40
#define RECFM_U 0xc0
#define RECFM_D 0x20
#define RECFM_T 0x20
#define RECFM_B 0x10
#define RECFM_S 0x08
#define RECFM_A 0x04
#define RECFM_M 0x02
#define RECFM_FB (RECFM_F | RECFM_B)
#define RECFM_VB (RECFM_V | RECFM_B)
#define DSORG_PS 0x4000
#define DSORG_PO 0x0200
/************************ Newsgroup status ***************************/
#define NO_SUCH_GROUP 0x80
#define NEW_GROUP 0x40
#define GROUP_FROM_NEWSRC 0x20
#define GROUP_LISTED 0x10
#define GROUP_SELECTED_UNREAD 0x08
#define GROUP_SELECTED_READ 0x04
#define GROUP_ERROR 0x02
#define GROUP_IN_TABLE 0x01
#define GROUP_SELECTED (GROUP_SELECTED_UNREAD | GROUP_SELECTED_READ)
/* Note that the test GroupSelected means unread OR read, but the
* assignment SetGroupSelected means set unread AND read selected
* assignment OffGroupSelected means set unread AND read unselected.
*/
#define NoSuchGroup(X) ((X)->status & NO_SUCH_GROUP)
#define NewGroup(X) ((X)->status & NEW_GROUP)
#define GroupFromNewsrc(X) ((X)->status & GROUP_FROM_NEWSRC)
#define GroupListed(X) ((X)->status & GROUP_LISTED)
#define GroupSelectedUnread(X) ((X)->status & GROUP_SELECTED_UNREAD)
#define GroupSelectedRead(X) ((X)->status & GROUP_SELECTED_READ)
#define GroupError(X) ((X)->status & GROUP_ERROR)
#define GroupInTable(X) ((X)->status & GROUP_IN_TABLE)
#define GroupSelected(X) ((X)->status & GROUP_SELECTED)
#define SetNoSuchGroup(X) (X)->status |= NO_SUCH_GROUP
#define SetNewGroup(X) (X)->status |= NEW_GROUP
#define SetGroupFromNewsrc(X) (X)->status |= GROUP_FROM_NEWSRC
#define SetGroupListed(X) (X)->status |= GROUP_LISTED
#define SetGroupSelectedUnread(X) (X)->status |= GROUP_SELECTED_UNREAD
#define SetGroupSelectedRead(X) (X)->status |= GROUP_SELECTED_READ
#define SetGroupError(X) (X)->status |= GROUP_ERROR
#define SetGroupInTable(X) (X)->status |= GROUP_IN_TABLE
#define SetGroupSelected(X) (X)->status |= GROUP_SELECTED
#define OffNoSuchGroup(X) (X)->status &= ~NO_SUCH_GROUP
#define OffNewGroup(X) (X)->status &= ~NEW_GROUP
#define OffGroupFromNewsrc(X) (X)->status &= ~GROUP_FROM_NEWSRC
#define OffGroupListed(X) (X)->status &= ~GROUP_LISTED
#define OffGroupSelectedUnread(X) (X)->status &= ~GROUP_SELECTED_UNREAD
#define OffGroupSelectedRead(X) (X)->status &= ~GROUP_SELECTED_READ
#define OffGroupError(X) (X)->status &= ~GROUP_ERROR
#define OffGroupInTable(X) (X)->status &= ~GROUP_IN_TABLE
#define OffGroupSelected(X) (X)->status &= ~GROUP_SELECTED
#define GroupListedOnly(X) (GroupListed(X) && !GroupSelected(X))
#define GroupFromNNTP(X) (GroupListed(X) || GroupSelected(X))
#define GroupFromNewsrcOnly(X) (GroupFromNewsrc(X) && \
!GroupListed(X) && \
!GroupSelected(X))
#define BogusGroup(X) (!GroupListed(X) && !GroupSelected(X))
#define ClearGroupStatus(X) (X)->status = 0x00
#define NullGroupStatus(X) ((X)->status == 0x00)
/************************* Article status ****************************/
#define NO_SUCH_ARTICLE 0x80
#define ARTICLE_ABSENT 0x40
#define ARTICLE_ERROR 0x20
#define ARTICLE_BAD_DATA 0x10
#define ARTICLE_HEAD_RETRIEVED 0x08
#define ARTICLE_BODY_RETRIEVED 0x04
#define ARTICLE_RETRIEVED (ARTICLE_HEAD_RETRIEVED | \
ARTICLE_BODY_RETRIEVED)
#define NoSuchArticle(X) ((X)->status & NO_SUCH_ARTICLE)
#define ArticleAbsent(X) ((X)->status & ARTICLE_ABSENT)
#define ArticleError(X) ((X)->status & ARTICLE_ERROR)
#define ArticleBadData(X) ((X)->status & ARTICLE_BAD_DATA)
#define ArticleHeadRetrieved(X) ((X)->status & ARTICLE_HEAD_RETRIEVED)
#define ArticleBodyRetrieved(X) ((X)->status & ARTICLE_BODY_RETRIEVED)
#define SetNoSuchArticle(X) (X)->status |= NO_SUCH_ARTICLE
#define SetArticleAbsent(X) (X)->status |= ARTICLE_ABSENT
#define SetArticleError(X) (X)->status |= ARTICLE_ERROR
#define SetArticleBadData(X) (X)->status |= ARTICLE_BAD_DATA
#define SetArticleHeadRetrieved(X) (X)->status |= ARTICLE_HEAD_RETRIEVED
#define SetArticleBodyRetrieved(X) (X)->status |= ARTICLE_BODY_RETRIEVED
#define OffNoSuchArticle(X) (X)->status &=~NO_SUCH_ARTICLE
#define OffArticleAbsent(X) (X)->status &=~ARTICLE_ABSENT
#define OffArticleError(X) (X)->status &=~ARTICLE_ERROR
#define OffArticleBadData(X) (X)->status &=~ARTICLE_BAD_DATA
#define OffArticleHeadRetrieved(X) (X)->status &=~ARTICLE_HEAD_RETRIEVED
#define OffArticleBodyRetrieved(X) (X)->status &=~ARTICLE_BODY_RETRIEVED
#define ArticleRetrieved(X) ((X)->status & ARTICLE_RETRIEVED)
#define SetArticleRetrieved(X) (X)->status |= ARTICLE_RETRIEVED
#define OffArticleRetrieved(X) (X)->status &= ~ARTICLE_RETRIEVED
#define ClearArticleStatus(X) (X)->status = 0x00
#define NullArticleStatus(X) ((X)->status == 0x00)
/************************* Article vector ****************************/
/*
* *** IMPORTANT! *** The hack of storing a vector of VARKs (which are
* both pointers and status bits) depends on malloc() returning storage
* for a struct on a doubleword boundary on MVS. This allows us to
* treat the low-order 3 bits of the pointer as trash so that we can
* store status bits in it. If this is not true, then this whole
* technique will collapse like a house of cards, or else you should
* stick a dummy double element into the newsarticle struct to make it
* so.
*/
/*
* Each article "pointer" (VARK) looks like this:
*
* -------------------------------------
* | | | | |
* | pointer to article | . | . | . |
* | | | | |
* -------------------------------------
* ^ ^ ^
* where pointer is one of | | |
* NULL - no article | | '--- 1 = Read, 0 = Unread
* MISSING - article missing | | |
* or the actual pointer | '------} 1 = Eligible, 0 = Ineligible
* |
* '----------} 1 = I know, 0 = I don't know
*
* 10 = Ineligible (not in table)
* 11 = Eligible (in table)
* 00 = Don't know yet
* 01 cannot occur
*
*/
#define VARK unsigned int
#define GETVARK(X,Y) ((X)->article_vector\
[(Y)-(X)->vector_first])
#define GETVARKFIRST(X) ((X)->article_vector[0])
#define GETVARKLAST(X) ((X)->article_vector\
[(X)->article_vector_len-1])
#define VARK2PARTICLE(X) (struct newsarticle *) \
(((unsigned int)(X)) & 0xfffffff8)
#define VARK2NUMBER(X,Y) (((Y)-(X)->article_vector) \
+ (X)->vector_first)
#define VARK2BITS(X) ((unsigned int)(X) & 0x00000007)
#define VARK2READNESS(X) ((unsigned int)(X) & 0x00000001)
#define VARK2ELIGIBILITY(X) ((unsigned int)(X) & 0x00000002)
#define VARK2KNOWLEDGE(X) ((unsigned int)(X) & 0x00000004)
#define V_READNESS(X,Y) VARK2READNESS(GETVARK(X,Y))
#define V_ELIGIBILITY(X,Y) VARK2ELIGIBILITY(GETVARK(X,Y))
#define V_KNOWLEDGE(X,Y) VARK2KNOWLEDGE(GETVARK(X,Y))
#define V_NULL_ARTICLE (struct newsarticle *)0
#define V_MISSING_ARTICLE (struct newsarticle *)np
#define VARKMISSING (unsigned int)np
#define VARKNULL (unsigned int)0
#define V_UNREAD_BIT 0x00000000
#define V_READ_BIT 0x00000001
#define V_INELIGIBLE_BIT 0x00000000
#define V_ELIGIBLE_BIT 0x00000002
#define V_UNKNOWN_BIT 0x00000000
#define V_KNOWN_BIT 0x00000004
#define V_KNOWN_ELIGIBLE (V_KNOWN_BIT + V_ELIGIBLE_BIT)
#define V_KNOWN_INELIGIBLE (V_KNOWN_BIT + V_INELIGIBLE_BIT)
#define SetUnread(X) X &= ~V_READ_BIT
#define SetRead(X) X |= V_READ_BIT
#define SetNull(X) X = VARKNULL
/* Note that whenever you set something missing, you also set it
* ineligible for table display.
*/
#define SetMissing(X) X = (VARK)\
(VARKMISSING | \
VARK2READNESS(X) | \
V_KNOWN_INELIGIBLE)
#define SetMissingUnread(X) X = (VARK)\
(VARKMISSING | \
V_UNREAD_BIT | \
V_KNOWN_INELIGIBLE)
#define SetMissingRead(X) X = (VARK)\
(VARKMISSING | \
V_READ_BIT | \
V_KNOWN_INELIGIBLE)
#define SetEligible(X) X |= V_ELIGIBLE_BIT
#define SetIneligible(X) X &= ~V_ELIGIBLE_BIT
#define SetKnown(X) X |= V_KNOWN_BIT
#define SetUnknown(X) X &= ~V_KNOWN_BIT
#define SetKnownEligible(X) SetKnown(X), SetEligible(X)
#define SetKnownIneligible(X) SetKnown(X), SetIneligible(X)
/* to get exact readness, use: VARK2READNESS(X) == V_whatever */
#define IsRead(X) ((X) & V_READ_BIT)
#define IsUnread(X) (!IsRead(X))
#define IsEligible(X) ((X) & V_ELIGIBLE_BIT)
#define IsIneligible(X) (!IsEligible(X))
#define IsKnown(X) ((X) & V_KNOWN_BIT)
#define IsUnknown(X) (!IsKnown(X))
#define IsKnownEligible(X) ((X)&V_KNOWN_ELIGIBLE==V_KNOWN_ELIGIBLE)
#define IsKnownIneligible(X) ((X)&V_KNOWN_ELIGIBLE==V_KNOWN_INELIGIBLE)
#define IsNull(X) (VARK2PARTICLE(X) == V_NULL_ARTICLE)
#define IsMissing(X) (VARK2PARTICLE(X) == V_MISSING_ARTICLE)
#define IsPresent(X) (!IsMissing(X))
#define IsMissingUnread(X) (IsMissing(X) && IsUnread(X))
#define IsMissingRead(X) (IsMissing(X) && IsRead(X))
#define IsPresentUnread(X) (IsPresent(X) && IsUnread(X))
#define IsPresentRead(X) (IsPresent(X) && IsRead(X))
#define NOTIFY_MSG 1
#define WARNING_MSG 2
#define CRITICAL_MSG 3
#define WARN1(X) NNMpmsg(np,NOTIFY_MSG,NULL,X)
#define WARN2(X,Y) NNMpmsg(np,NOTIFY_MSG,NULL,X,Y)
#define WARN3(X,Y,Z) NNMpmsg(np,NOTIFY_MSG,NULL,X,Y,Z)
#define WARN4(X,Y,Z,W) NNMpmsg(np,NOTIFY_MSG,NULL,X,Y,Z,W)
#define ERR1(X) NNMpmsg(np,WARNING_MSG,NULL,X)
#define ERR2(X,Y) NNMpmsg(np,WARNING_MSG,NULL,X,Y)
#define ERR3(X,Y,Z) NNMpmsg(np,WARNING_MSG,NULL,X,Y,Z)
#define ERR4(X,Y,Z,W) NNMpmsg(np,WARNING_MSG,NULL,X,Y,Z,W)
#define CRIT1(X) NNMpmsg(np,CRITICAL_MSG,NULL,X)
#define CRIT2(X,Y) NNMpmsg(np,CRITICAL_MSG,NULL,X,Y)
#define CRIT3(X,Y,Z) NNMpmsg(np,CRITICAL_MSG,NULL,X,Y,Z)
#define MSG(X) (MSG_is_obsolete,)
#define GETMAIN(Ptr,Typ,Siz,For) \
NNMgetm(np,(char **)&(Ptr),(sizeof(Typ))*(Siz),For)
#define FREEMAIN(Ptr,For) if (Ptr) {NNMfreem(np,(char *)Ptr,For);}
/****** Data and structure definitions. ******************************/
enum scroll {NO_SCROLL, UP, DOWN, LEFT, RIGHT, LOCATE};
enum extreq {EXTRACT_IT, PRINT_IT};
enum data_set_type {PDS, SEQ, UNK, JES};
enum list_option {LIST_ALL, LIST_NEW, LIST_ALL_DISCONNECT};
enum choose_reason {RETRIEVE, MARK_ONLY};
enum socket_retval {
SERVER_READ_OK,
SERVER_READ_ERROR,
SERVER_BUFFER_ERROR,
SERVER_NO_MORE
};
enum display_retval {
DISPLAY_REPEAT,
DISPLAY_EXIT,
DISPLAY_ERROR,
DISPLAY_FAILURE
};
enum user_option {
OPTION_ALL,
OPTION_HEADER,
OPTION_OTHER,
OPTION_VIEW
};
enum article_cookie {
NULL_ARTICLE_COOKIE ,
UNREAD_THIS_ARTICLE ,
NEXT_ARTICLE ,
PREV_ARTICLE ,
NEXT_TABLED_ARTICLE ,
PREV_TABLED_ARTICLE ,
NEXT_UNREAD_ARTICLE ,
PREV_UNREAD_ARTICLE ,
NEXT_THREAD_ARTICLE ,
PREV_THREAD_ARTICLE ,
FIRST_THREAD_ARTICLE ,
LAST_THREAD_ARTICLE ,
NEW_THREAD_ARTICLE ,
REDISPLAY_ARTICLE
};
typedef struct _textunit TEXTUNIT;
typedef unsigned int IPADDRESS;
typedef enum scroll SCROLL;
typedef enum extreq EXTREQ;
struct textline {
struct textline *next;
short text_length;
short tab_expanded_text_length;
char *tab_expanded_text;
char text[1]; /* dummy */
};
struct texthdr {
int text_line_count;
short text_max_length;
short text_max_tab_expanded_length;
struct textline *text_body_line;
struct textline *first_text_line;
struct textline *current_text_line;
struct textline *last_text_line;
};
/* see note on newsarticle struct under article vector stuff */
struct newsarticle {
char *from;
char *subject;
char *date;
char *message_id;
char *csubject;
int number;
char action;
char status;
struct texthdr thdr;
};
struct newsgroup {
struct newsgroup *next;
struct newsgroup *next2;
struct newsgroup *next3;
char *saved_newsrc_line;
VARK *article_vector;
VARK **sort_vector;
int low_number;
int high_number;
int vector_first;
int vector_last;
int article_count;
int unread_count;
int sort_count;
int article_vector_len;
int registered;
char status;
char saved_newsrc_data [12];
char name [1]; /* dummy len */
};
struct cmddesc {
char command_name[COMMANDSIZE];
Bool (*command_processor)();
};
struct seldesc {
char selection_code;
Bool (*selection_processor)();
};
struct tabledesc {
char *command_variable;
struct cmddesc *first_cmddesc;
struct seldesc *first_seldesc;
struct cmddesc *next_cmddesc;
};
struct tablevector {
struct tabledesc *newsgroup_display_table;
struct tabledesc *article_display_table;
struct tabledesc *text_display_table;
};
struct _textunit {
unsigned short key;
unsigned short num;
struct {
unsigned short len;
char prm[80];
} ent;
};
struct extraction {
int from_article_number;
int to_article_number;
int article_count;
enum data_set_type mode;
void (*closer)();
Bool appending;
Bool blanking;
Bool tab_expanding;
Bool ejecting;
Bool formfeeding;
char panelname [9];
char dsname [65];
char separator [81];
char member_prefix [9];
char ddname [9];
char member [9];
};
struct countdown {
Bool do_update;
int done;
int to_do;
};
struct nncb {
char *server_buf;
char *client_buf;
char *nntp_command;
char *nntp_message_text;
char *extract_separator_line;
struct newsgroup *first_newsgroup;
struct newsgroup *current_newsgroup;
struct newsgroup *last_newsgroup;
struct newsgroup *first_newsgroup_alt;
struct newsgroup *last_added_newsgroup;
struct tablevector *display_table_vector;
struct extraction *extractionp;
FILE *debug_file;
FILE *newsrc_file;
FILE *extract_file;
FILE *batch_infile;
FILE *batch_outfile;
void *batch_hook;
#ifdef FETCH
int (*isplink_pointer)();
int (*ispexec_pointer)();
#endif
struct newsarticle *article_being_viewed;
VARK **top_sorted_article;
VARK **current_sortvark;
int top_article;
int ispfrc;
int nntp_message_num;
int socknum;
int g_bytes_returned;
int g_buf_index;
int new_newsgroup_count;
int article_rows;
int updatefreq; /* ddi */
int text_find_left_bound;
int text_find_right_bound;
enum article_cookie another_article;
struct texthdr thdr;
IPADDRESS client_ip_address;
IPADDRESS server_ip_address;
time_t lasttime; /* ddi */
time_t firstime; /* ddi */
Bool test_mode;
Bool debug_mode;
Bool batch_mode;
Bool quit;
Bool time_to_go_home;
Bool server_has_something_pending;
Bool server_finished_replying;
Bool sending_text;
Bool receiving_text;
Bool something_to_print;
Bool dont_read;
Bool connected_to_server;
Bool connection_broken;
Bool closing_connection;
Bool reconnect_in_progress;
Bool posting_allowed;
Bool newsgroup_selected;
Bool newsgroup_not_found;
Bool newsgroup_order_changed;
Bool brand_new_newsrc;
Bool newsgroup_criterion_changed;
Bool show_all_newsgroups;
Bool following_up;
Bool extract_tab_expanding;
Bool extract_appending;
Bool extract_blank_before_separator;
Bool extract_ejecting;
Bool extract_formfeeding;
Bool extract_write_error;
Bool extract_close_error;
Bool please_locate_group;
Bool please_find_group;
Bool repeat_find;
Bool article_criterion_changed;
Bool article_repeat_find;
Bool article_text_not_found;
Bool warn_overwrite;
Bool warn_append;
Bool dont_reissue_socket_command;
Bool show_all_articles;
Bool update_adding_newsgroups;
Bool update_rewriting_newsrc;
Bool update_retrieving_articles;
Bool bypass_header_retrieval;
Bool unread_articles_only;
Bool setmsg;
Bool newsgroup_autoscroll;
Bool article_autoscroll;
Bool sort_by_subject;
Bool xhdr_not_available;
Bool newsgroup_autocursor;
Bool article_autocursor;
Bool setcursor;
Bool printing;
Bool dont_reconnect;
char newsgroup_order;
char newsgroup_find_option;
char article_find_option;
char preselection;
char barchar; /* ddi */
char text_dispchar;
char text_find_what;
char text_find_type;
char text_find_trans;
char newsrc_to_open [ 12];
char nnrfcopt [ 2];
char nnrfcinc [256];
char nnrfcexc [256];
char maildsn [ 64];
char messageid [128];
char nnregnng [ 9];
char nngroup [GROUP_NAME_SIZE+1];
char nnserver [MAXHOSTNAMELEN+1];
char nnclient [MAXHOSTNAMELEN+1];
char client_hostname [MAXHOSTNAMELEN+1];
char client_ip_addrstr [16];
char server_hostname [MAXHOSTNAMELEN+1];
char server_ip_addrstr [16];
char g_buf [READ_BYTES];
char newsgroup_locate_string [GROUP_NAME_SIZE+1];
char newsgroup_only_string [GROUP_NAME_SIZE+1];
char newsgroup_find_string [GROUP_NAME_SIZE+1];
char article_only_string [GROUP_NAME_SIZE+1];
char article_find_string [GROUP_NAME_SIZE+1];
char lastNGdate [7]; /* ddi */
char lastNGtime [7]; /* ddi */
char selsubj [81]; /* ddi */
char text_find_string [GROUP_NAME_SIZE+1];
};
#ifdef MVS
#ifndef I370
extern char ebcdictoascii[];
extern char asciitoebcdic[];
#endif
#endif
#ifndef FETCH
extern int isplink();
extern int ispexec();
#endif
/****** Procedure and function declarations. *************************/
extern struct newsgroup *NNMaddng(struct nncb *, char *);
extern void NNMadjua(struct nncb *, struct newsgroup *,
int, int, int);
extern void NNMallav(struct nncb *, struct newsgroup *,
int, int);
extern Bool NNMalloc(char *, char *, enum data_set_type,
int);
extern Bool NNMauth (struct nncb *);
extern int NNMbatch(struct nncb *);
extern void NNMbtext(struct nncb *, struct texthdr *,
FILE *);
extern Bool NNMcar (struct nncb *,struct newsgroup *,
int,VARK *,struct newsarticle **,
struct countdown *,
enum choose_reason);
extern void NNMclrng(struct nncb *);
extern void NNMclrtx(struct nncb *,struct newsarticle *);
extern void NNMcnrf (struct nncb *, char *, Fool);
extern Bool NNMconn (struct nncb *);
extern char *NNMcopy (struct nncb *, char *);
extern Bool NNMdcan (struct nncb *,struct newsgroup *,
struct newsarticle *);
extern void NNMdfail(int,__S99parms *);
extern void NNMdisc (struct nncb *);
extern int NNMdispl(struct nncb *, char *);
extern Bool NNMdlang(struct nncb *, enum list_option);
extern void NNMdmail(struct nncb *,struct newsgroup *,
struct newsarticle *);
extern enum display_retval NNMdmenu(struct nncb *, Bool (**)());
extern struct newsgroup *NNMdng (struct nncb *,
struct newsgroup *, char *);
extern void NNMdnntp(struct nncb *, char *);
extern void NNMdoit (struct nncb *,
struct newsarticle *, Fool);
extern void NNMdpost(struct nncb *,struct newsgroup *,
struct newsarticle *);
extern void NNMdsopt(struct nncb *,char *);
extern void NNMdump (struct nncb *,char *, char *, int);
extern void NNMesrvr(struct nncb *);
extern Bool NNMestng(struct nncb *, char *);
extern void NNMfreem(struct nncb *,char *,char *);
extern FILE *NNMgetds(struct nncb *,struct extraction *);
extern void NNMgetm (struct nncb *,char **,int,char *);
extern Bool NNMgsrvl(struct nncb *, char **);
extern void NNMierr (struct nncb *);
extern int NNMiget (struct nncb *, char *);
extern void NNMimsg (struct nncb *, char *);
extern void NNMinit (struct nncb *);
extern Bool NNMispf (struct nncb *, char *);
extern Bool NNMivget(struct nncb *, char *, char *,int);
extern Bool NNMivput(struct nncb *, char *, char *,int);
extern void NNMmarr(struct nncb *, struct newsgroup *,
VARK *);
extern void NNMmaru(struct nncb *, struct newsgroup *,
VARK *);
extern void NNMnntp (struct nncb *);
extern void NNMonrf (struct nncb *, char *);
extern struct textline *NNMouttx(struct nncb *, char *,
struct newsarticle *);
extern Bool NNMpick (struct nncb *,struct newsarticle *);
extern Bool NNMpng (struct nncb *,struct newsgroup *,
Fool,Fool);
extern Bool NNMqar (struct nncb *,struct newsarticle *);
extern void NNMqng (struct nncb *,struct newsgroup *);
extern struct newsarticle *NNMrarh (struct nncb *,struct newsgroup *,
VARK *,int,struct countdown *);
extern int NNMrart (struct nncb *,struct newsgroup *,
Fool,Fool);
extern void NNMrbfm (struct nncb *);
extern Bool NNMrecon(struct nncb *);
extern void NNMrperr(struct nncb *);
extern Bool NNMsave (struct nncb *,char *);
extern Bool NNMsockt(struct nncb *);
extern void NNMsopt (struct nncb *, enum user_option);
extern Bool NNMsort (struct nncb *,struct newsgroup *);
extern void NNMssrvr(struct nncb *);
extern char *NNMstrlc(char *, char *);
extern Bool NNMsumat(char *, char *);
extern int NNMtso (char *);
extern Bool NNMunalc(char *);
extern void NNMupdt (struct nncb *,struct countdown *,
char *);
extern Bool NNMvar (struct nncb *,struct newsgroup *);
extern void NNMview (struct nncb *,struct newsgroup *,
struct newsarticle *,
struct texthdr *,
char *);
extern Bool NNMvng (struct nncb *);
extern void NNMvtx (struct nncb *,struct newsgroup *,
struct newsarticle *);
extern Bool NNMxartt(struct nncb *,struct newsgroup *,
enum data_set_type);
extern Bool NNMxartx(struct nncb *,struct newsgroup *,
enum data_set_type);
extern Bool NNMxlist(struct nncb *,enum data_set_type);
extern Bool NNMxtx (struct nncb *,struct newsarticle *,
Fool);
#ifndef SUPPRESS_V_DECLARATION
extern void NNMpmsg (struct nncb *,int,char *,char *,
...);
#endif
#ifdef C370V2
#pragma checkout(resume)
#endif
./ ADD NAME=NNBATCH,SSI=01010007
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/* ------------------ "nnbatch.h" include member ------------------- */
/* Include file for NNMVS batch mode operations. */
#define FIRST_ARTICLE_IN_RANGE (-1)
#define LAST_ARTICLE_IN_RANGE (2147483647)
#define MIN_RESERVED_WORD_LENGTH 2
#define MAX_RESERVED_WORD_LENGTH 10
#define ANYTYPE void *
#define PEEK() (NNMbgtok(np,bp,TOKEN_PEEK) ? &bp->nextok : NULL)
#define EAT() (void)NNMbgtok(np,bp,TOKEN_READ)
#define SETA(X,Y) NNMbvput(np,bp,(X),NUMBER_SYMTYPE,(ANYTYPE)(Y))
#define SETB(X,Y) NNMbvput(np,bp,(X),FLAG_SYMTYPE, (ANYTYPE)(Y))
#define SETC(X,Y) NNMbvput(np,bp,(X),STRING_SYMTYPE,(ANYTYPE)(Y))
#define GETA(X) (int) NNMbvget(np,bp,(X),NUMBER_SYMTYPE)
#define GETB(X) (Fool) NNMbvget(np,bp,(X),FLAG_SYMTYPE)
#define GETC(X) (char *)NNMbvget(np,bp,(X),STRING_SYMTYPE)
typedef struct newscmd *(*CommandParser) ();
typedef void (*CommandExecutor) ();
enum tokentype {NO_TOKEN,
EOL_TOKEN,
EOF_TOKEN,
AND_TOKEN,
OR_TOKEN,
NOT_TOKEN,
GT_TOKEN,
LT_TOKEN,
EQ_TOKEN,
NE_TOKEN,
GE_TOKEN,
LE_TOKEN,
LPAR_TOKEN,
RPAR_TOKEN,
PLUS_TOKEN,
MINUS_TOKEN,
TIMES_TOKEN,
OVER_TOKEN,
SEMI_TOKEN,
WORD_TOKEN,
NUMBER_TOKEN,
STRING_TOKEN,
ERROR_TOKEN
};
enum tokenfunc {
TOKEN_PEEK,
TOKEN_READ,
TOKEN_FLUSH
};
enum batchmode {
INITIAL_MODE,
PER_NEWSGROUP_MODE,
PER_ARTICLE_MODE,
TEXT_MODE,
ERROR_MODE,
ANY_MODE
};
enum marking_mode {
MARKING_READ,
MARKING_UNREAD
};
enum extracting_mode {
NO_EXTRACTING_MODE,
EXTRACTING_ALL,
EXTRACTING_READ,
EXTRACTING_UNREAD
};
enum which_newsgroups {
NO_NEWSGROUPS,
ALL_NEWSGROUPS,
REGISTERED_NEWSGROUPS,
UNREGISTERED_NEWSGROUPS,
NAMED_NEWSGROUPS,
MASKED_NEWSGROUPS
};
enum which_articles {
NO_ARTICLES,
ALL_ARTICLES,
READ_ARTICLES,
UNREAD_ARTICLES,
RANGED_ARTICLES
};
enum symtype {
NO_SYMTYPE,
STRING_SYMTYPE,
NUMBER_SYMTYPE,
FLAG_SYMTYPE
};
/*-------------------------------------------------------------------*
* Define structures to handle expressions computed at run time.
*-------------------------------------------------------------------*/
#include "nnptree.h" /* Grammar to handle general expressions */
/*-------------------------------------------------------------------*
* newsgroup_crit: defines criteria for selecting newsgroups.
* Corresponds to xxx in:
* FOR xxx WHEN (yyy) DO zzz
* in top-level mode.
*-------------------------------------------------------------------*/
struct newsgroup_crit {
enum which_newsgroups which;
struct ptree *groups;
};
/*-------------------------------------------------------------------*
* article_crit: defines criteria for selecting articles.
* Corresponds to xxx in:
* FOR xxx WHEN (yyy) DO zzz
* in per-newsgroup mode.
*-------------------------------------------------------------------*/
struct article_crit {
enum which_articles which;
struct ptree *first;
struct ptree *last;
};
/*-------------------------------------------------------------------*
* for_newsgroups: defines what to do for each newsgroup and which
* newsgroups were selected. Corresponds to:
* FOR xxx WHEN (yyy) DO zzz
* in top-level mode.
*-------------------------------------------------------------------*/
struct for_newsgroups {
struct ptree *filter;
struct newsgroup_crit crit;
struct cmdtree *treep;
};
/*-------------------------------------------------------------------*
* for_articles: defines what to do for each article and which
* articles were selected. Corresponds to:
* FOR xxx WHEN (yyy) DO zzz
* in per-newsgroup mode.
*-------------------------------------------------------------------*/
struct for_articles {
struct ptree *filter;
struct article_crit crit;
struct cmdtree *treep;
};
/*-------------------------------------------------------------------*
* OK, here are defined the kinds of commands.
*-------------------------------------------------------------------*/
struct initial_mode_cmd {
struct for_newsgroups fors;
};
struct per_newsgroup_mode_cmd {
struct for_articles fors;
};
struct if_cmd {
struct ptree *condition;
struct cmdtree *thencmds;
struct cmdtree *elsecmds;
};
struct set_cmd {
struct ptree *ptreep;
char * set_symbol;
enum symtype set_type;
};
struct mark_cmd {
enum marking_mode marking;
};
struct extract_cmd {
enum extracting_mode extracting;
};
struct miscellaneous_cmd {
struct ptree *ptreep;
};
union some_mode_cmd {
struct initial_mode_cmd icmd;
struct per_newsgroup_mode_cmd ncmd;
struct if_cmd fcmd;
struct set_cmd scmd;
struct mark_cmd rcmd;
struct extract_cmd xcmd;
struct miscellaneous_cmd mcmd;
};
/*-------------------------------------------------------------------*
* newscmd: defines format of operations to perform on something.
*-------------------------------------------------------------------*/
struct newscmd {
enum batchmode mode;
CommandExecutor proc;
union some_mode_cmd cmd;
};
struct cmdtree {
struct cmdtree *next;
struct newscmd *cmd;
};
#define MAX_SYMBOL_LENGTH 16
/*-------------------------------------------------------------------*
* symtab: defines symbol table that holds values of variables.
* The complete symbol table is a classic binary tree of
* symtab structs.
*
* To allocate, take length of variable value string,
* then add that to offsetof(struct symtab,symval) to get total.
*-------------------------------------------------------------------*/
struct symtab {
char symvar[MAX_SYMBOL_LENGTH];
struct symtab *left;
struct symtab *right;
enum symtype type;
int symnum;
int vallen;
char symval[1]; /* dummy for alloc */
};
struct token {
enum tokentype type;
char string [260];
int number;
};
struct batch {
struct cmdtree *treetop;
struct cmdtree *treebottom;
struct symtab *symtabp;
struct newsgroup *gp;
VARK *vp;
struct newscmd *ifcmd;
char *inchar;
char *reserved_words;
char *outfilename;
FILE *outfp;
int input_errors;
int request_errors;
enum batchmode mode;
enum data_set_type extractds_mode;
CommandParser endproc;
jmp_buf jump;
struct token curtok;
struct token nextok;
Bool exactcase;
Bool syntax_error;
Bool runtime_error;
Bool eof;
Bool quit;
Bool stop_at_newline;
Bool tokens_read;
Bool newsgroups_retrieved;
char inline [260];
char extractds [81];
char extractds_part1 [81];
char extractds_part2 [81];
char extractds_member [81];
};
extern ANYTYPE NNMbbexp(struct nncb *, struct batch *,
struct ptree *,enum symtype);
extern Bool NNMbconn(struct nncb *, struct batch *);
extern struct symtab *NNMbdecl(struct nncb *, struct batch *, char *,
enum symtype, ANYTYPE);
extern void NNMbflus(struct nncb *, struct batch *);
extern CommandParser NNMbgcmd(struct nncb *, struct batch *);
extern struct cmdtree *NNMbgdo (struct nncb *, struct batch *,
enum batchmode);
extern struct ptree *NNMbgexp(struct nncb *, struct batch *,
enum symtype);
extern Bool NNMbgtok(struct nncb *, struct batch *,
enum tokenfunc);
extern FILE *NNMbsout(struct nncb *, struct batch *);
extern void NNMbsynt(struct nncb *, struct batch *,
char *, int, char *);
extern void NNMbtras(struct nncb *, struct batch *, char *);
extern ANYTYPE NNMbvget(struct nncb *, struct batch *, char *,
enum symtype);
extern void NNMbvput(struct nncb *, struct batch *, char *,
enum symtype, ANYTYPE);
extern void NNMbxfar (struct nncb *, struct batch *,
struct newscmd *);
extern void NNMbxfng (struct nncb *, struct batch *,
struct newscmd *);
./ ADD NAME=NNPTREE,SSI=01000033
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/* ----------------- "nnptree.h" include member -------------------- */
#define ALLOC(X,Y) GETMAIN(X,struct Y,1,#Y);\
if (!(X)) longjmp(bp->jump,ERROR_GETMAIN_FAILURE)
#define ERR(X) (NNMbsynt(np,bp,bp->curtok.string,0,X),\
longjmp(bp->jump,ERROR_BAD_EXPRESSION))
#define LOSE longjmp(bp->jump,ERROR_SCAN_ERROR)
#define ERROR_NONE 0
#define ERROR_TYPE_MISMATCH 1
#define ERROR_ZERODIVIDE 2
#define ERROR_GETMAIN_FAILURE 3
#define ERROR_BAD_EXPRESSION 4
#define ERROR_SCAN_ERROR 5
/*-------------------------------------------------------------------*
* ptree: defines structure of expressions used by various commands,
* including SET, PUT and NNTP. When these commands are parsed,
* a ptree structure is built to be interpreted when the command is
* executed. The structure represents one of the following:
*
* - a string expression (concatenated strings or string vars)
* - a numeric expression (number, number var or arithmetic expr)
* - a flag expression (flag, flag var or logical expr)
*
*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*
* treetype: type of an expression tree.
*-------------------------------------------------------------------*/
enum treetype {
NO_TREETYPE,
STRING_TREETYPE,
NUMBER_TREETYPE,
FLAG_TREETYPE
};
/*-------------------------------------------------------------------*
* rhstype: type of an expression subtree, based on the RHS of a
* production. Defines the structure of the components
* that make up this subtree. Note that the types are
* meaningful only within a given production (LHS) type.
*-------------------------------------------------------------------*/
enum rhstype {
NO_RHSTYPE,
RHSTYPE_A,
RHSTYPE_B,
RHSTYPE_C,
RHSTYPE_D,
RHSTYPE_E
};
/*-------------------------------------------------------------------*
* optype: type of an operator
*-------------------------------------------------------------------*/
enum optype {
NO_OP,
AND_OP,
OR_OP,
NOT_OP,
IN_OP,
EQ_OP,
NE_OP,
GT_OP,
LT_OP,
GE_OP,
LE_OP,
ADD_OP,
SUB_OP,
MUL_OP,
DIV_OP
};
/*-------------------------------------------------------------------*
* These types correspond to production LHS's.
*-------------------------------------------------------------------*/
typedef struct exp * Exp;
typedef struct choice * Choice;
typedef struct relation * Relation;
typedef struct value * Value;
typedef struct quantity * Quantity;
typedef struct term * Term;
typedef struct factor * Factor;
typedef struct unop * Unop;
typedef struct addop * Addop;
typedef struct mulop * Mulop;
typedef struct logop * Logop;
typedef struct relop * Relop;
typedef struct constant * Constant;
typedef struct variable * Variable;
typedef struct number * Number;
typedef struct string * String;
typedef struct flag * Flag;
/*-------------------------------------------------------------------*
* The following define the top-down LR(1) grammar.
*-------------------------------------------------------------------*/
struct exp {
enum rhstype r;
enum symtype s;
union {
struct {
Choice choice1;
} a;
struct {
/* "IF" */
Exp exp1;
/* "THEN" */
Exp exp2;
/* "ELSE" */
Exp exp3;
} b;
} u;
};
struct choice {
enum rhstype r;
enum symtype s;
union {
struct {
Relation relation1;
} a;
struct {
Choice choice1;
Logop logop2;
Relation relation3;
} b;
} u;
};
struct relation {
enum rhstype r;
enum symtype s;
union {
struct {
Value value1;
} a;
struct {
Value value1;
Relop relop2;
Value value3;
} b;
} u;
};
struct value {
enum rhstype r;
enum symtype s;
union {
struct {
Quantity quantity1;
} a;
struct {
Value value1;
Quantity quantity2;
} b;
} u;
};
struct quantity {
enum rhstype r;
enum symtype s;
union {
struct {
Term term1;
} a;
struct {
Quantity quantity1;
Addop addop2;
Term term3;
} b;
} u;
};
struct term {
enum rhstype r;
enum symtype s;
union {
struct {
Factor factor1;
} a;
struct {
Term term1;
Mulop mulop2;
Factor factor3;
} b;
} u;
};
struct factor {
enum rhstype r;
enum symtype s;
union {
struct {
Constant constant1;
} a;
struct {
Variable variable1;
} b;
struct {
Unop unop1;
Factor factor2;
} c;
struct {
/* "(" */
Exp exp1;
/* ")" */
} d;
} u;
};
struct constant {
enum rhstype r;
enum symtype s;
union {
struct {
Number number1;
} a;
struct {
String string1;
} b;
struct {
Flag flag1;
} c;
} u;
};
struct unop {
enum optype op1; /* + - ! ^ */
};
struct addop {
enum optype op1; /* + - */
};
struct mulop {
enum optype op1; /* * / */
};
struct logop {
enum optype op1; /* AND OR */
};
struct relop {
enum optype op1; /* EQ GT LE NE IN... */
};
struct variable {
enum symtype s;
char * variable1;
};
struct number {
enum symtype s;
int number1;
};
struct string {
enum symtype s;
char *string1;
};
struct flag {
enum symtype s;
Fool flag1; /* ON OFF TRUE FALSE */
};
/*-------------------------------------------------------------------*
* thing: describes entity to be returned from a ptree at run time
*-------------------------------------------------------------------*/
struct thing {
ANYTYPE val; /* char *, int, Fool */
enum symtype typ; /* string/number/flag*/
};
/*-------------------------------------------------------------------*
* ptree: expression tree. Root of string/number/flag expression
*-------------------------------------------------------------------*/
struct ptree {
enum symtype type; /* string/number/flag*/
Exp exp1; /* actual expression */
};
./ ADD NAME=NNSASC,SSI=01000006
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/* ------------------- "nnsasc.h" include member ------------------- */
#ifdef SASC
#define I370
#include <dynam.h>
#define FETCH
__inline void (*fetch( const char *modname ))()
{
void (**fpp)();
loadm( modname, &fpp );
return( *fpp );
}
__inline int (*release( void (*fpp)() ))
{
unloadm( fpp );
return( 0 );
}
#ifndef __SVC99
#define __SVC99 1
#include <code.h>
struct __S99struc
{
unsigned char __S99RBLN; /* length of request block..20 */
unsigned char __S99VERB; /* verb code */
unsigned short __S99FLAG1; /* FLAGS1 field of SVC99 Req Block */
unsigned short __S99ERROR; /* error code field */
unsigned short __S99INFO; /* information reason code */
void *__S99TXTPP; /* address of text unit pointer list*/
int __reserved; /* reserved..will always be 0 */
unsigned int __S99FLAG2; /* FLAGS2 field..can only be filled */
/* in by APF authorized programs */
};
typedef struct __S99struc __S99parms;
__inline int svc99(__S99parms* svc99parmlist)
{ return( (_ldregs(R1, &svc99parmlist),
_code(0, 0x0a63),
_stregs(R15) ) );
}
#endif
#define FALSE 0
#define TRUE 1
#include <lcio.h>
#define MAXHOSTNAMELEN 64
#define __ctest(X) fprintf(stderr,\
"NNMVS: CTEST is not supported by this compiler.")
#endif
./ ADD NAME=NNUSER,SSI=01050047
/********************************************************************/
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
/********************************************************************/
/* ------------------- "nnuser.h" include member ------------------- */
/* Include file for locally customized values. */
/* Define levels of C/370 and TCP/IP. This controls support for
* fetching of non-C load modules and socket error reporting.
*/
/* #define C370V1 /* define this if C/370 Version 1 */
#define C370V2 /* define this if C/370 Version 2 or higher */
/* #define SASC /* define this if SAS/C compiler */
/* #define TCPIPV1 /* define this if TCP/IP Version 1 */
#define TCPIPV2 /* define this if TCP/IP Version 2 or higher */
/* #define SNSTCPIP /* define this if SNS/TCPAccess */
/* #define ISPFV2 /* define this if ISPF Version 2 or earlier */
#define ISPFV3 /* define this if ISPF Version 3 or later
/* Define the following defaults for your installation. */
/*
* Specify the "user name" portion of the "Sender:" address generated
* by posting and mailing requests.
*
*/
#define NNMVS_NAME "NNMVS"
/*
* Specify the name of the authorization file used to pass AUTHINFO
* requests to the server, if the server requires. This file should
* be readable only by NNMVS if possible. See the sample authorization
* file (AUTH) for the format.
*
*/
/* #define AUTHFILE "SYS4.NNTP.SYS" */
#undef AUTHFILE
/*
* Turn on for TCP-level debugging output (you probably don't want to
* unless your TCP/IP stuff is really broken and I can't help you).
*/
/* #define DEBUG */
#undef DEBUG
/*
* Define this if you want DEST, FORMS and UCS for print requests.
* Undefine it if you don't (you get just CLASS and COPIES).
*/
/* #define FULLSYSOUT */
#undef FULLSYSOUT
./ ENDUP
?!
//PANELS EXEC NNLOAD,TRK1='10',TO='PANELS'
//SYSIN DD DATA,DLM='?!'
./ ADD NAME=COPYRITE,SSI=01000028
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
./ ADD NAME=NNL,SSI=01010002
)ATTR
~ TYPE(INPUT) INTENS(HIGH) PAD('_')
# TYPE(INPUT) INTENS(LOW) CAPS(OFF)
$ TYPE(INPUT) INTENS(LOW) CAPS(ON)
)BODY
%--------------- NETNEWS SERVER SELECTION MENU -------------------------------
%Command ===>_ZCMD %Scroll ===>_AMT +
%
+Line commands: %D+(Delete) %I+(Insert) %R+(Replicate) %S+(Select)
%
% Server NEWSRC dsname
% -------------------------------------------- ------------------------------
)MODEL
%~Z%#SERVER $NEWSRC
)INIT
.ZVARS = '(NNSEL)'
&AMT = &ZSCML
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
&ZSCML = &AMT
VPUT (ZSCML) PROFILE
)END
/* Panel due to Leonard D. Woren <ldw@mvsa.usc.edu>. */
./ ADD NAME=NNM,SSI=01210007
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) COLOR(GREEN) CAPS(OFF)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
)BODY EXPAND(``)
%-`-`- MVS Network News Viewer -`-`-
%COMMAND ===>_ZCMD
+
+Select one of the following options:
+
+ %L+or%blank+ - List all newsgroups from server
+ %N +NEWGROUPS - List new newsgroups from server since last N or L
+ %A +ALL - Select items from all newsgroups listed in NEWSRC file
+ %R +REGISTERED - Select items from registered newsgroups in NEWSRC file
+ %G +GROUP - Go directly to the newsgroup named below
+ %NNTP+ - Enter native NNTP protocol commands
+ %OPTions+ - Specify NNMVS defaults
+ %X +EXIT - Bye
+
%Newsgroup name +(if option G selected)%===>^NNGROUPI
+
%News server host name+(or IP address) %===>_NNSERVER
+
%Name of NEWSRC data set %===>_NNNEWSRF
+
+Press!END+key to leave this menu.
)INIT
.HELP = TNNM
IF (&NNCURSOR = &Z)
IF (&NNSERVER = &Z)
.CURSOR = NNSERVER
ELSE
.CURSOR = ZCMD
ELSE
.CURSOR = &NNCURSOR
&ZCMD = &Z
IF (&NNREGNNG = &Z) &NNREGNNG = PROMPT
IF (&NNNEWSRF = &Z) &NNNEWSRF = NEWSRC
)PROC
IF (&NNGROUPI ^= &Z) VER(&ZCMD,NB)
IF (&ZCMD = ' ') &ZCMD = 'L' /* remove if you hate BLANK */
&ZCMD = TRANS(&ZCMD A,A R,R L,L G,G N,N
O,O OPT,O OPTIONS,O NNTP,P P,P X,X LD,Z *,?)
IF (&ZCMD ^= 'X') VER (&NNSERVER,NB)
IF (&ZCMD = 'G') VER (&NNGROUPI,NB)
&NNREGNNG = TRUNC(&NNREGNNG,1)
VER (&NNREGNNG,NB,LIST,Y,N,P)
VER (&NNNEWSRF,NB,DSNAME)
&TEMP1 = TRUNC(&NNNEWSRF,1)
&TEMP2 = .TRAIL
IF (&TEMP1 = '''')
&NNNEWSRC = TRUNC(&TEMP2,'''')
ELSE
&NNNEWSRC = '&ZPREFIX..&NNNEWSRF'
VPUT (NNGROUPI NNSERVER NNREGNNG NNNEWSRF) PROFILE
)END
./ ADD NAME=NNMDAR,SSI=010A0020
)ATTR DEFAULT(%+\)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
~ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
| AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
01 TYPE(DATAOUT) INTENS(LOW)
02 TYPE(DATAOUT) INTENS(HIGH)
03 TYPE(DATAIN) INTENS(LOW)
04 TYPE(DATAIN) INTENS(HIGH)
05 TYPE(DATAOUT) COLOR(GREEN)
06 TYPE(DATAOUT) COLOR(PINK)
07 TYPE(DATAOUT) COLOR(RED)
08 TYPE(DATAOUT) COLOR(TURQ)
09 TYPE(DATAOUT) COLOR(YELLOW)
0A TYPE(DATAIN) COLOR(BLUE)
0B TYPE(DATAIN) COLOR(PINK)
0C TYPE(DATAIN) COLOR(TURQ)
0D TYPE(DATAIN) COLOR(WHITE)
0E TYPE(DATAIN) COLOR(YELLOW)
)BODY EXPAND(``)
%&NNTHEAD
%COMMAND ===>~NNTCMD %SCROLL ===>^NNTS+
+ %
Article:%S+select%E+extract%P+print%M+mark%U+unmark%C+cancel%Status Date
_______________________________________________________________________________
|NNTDYNA |
)INIT
.HELP = TNNMT
IF (&NNTS = &Z) &NNTS = CSR
IF (&NNTCSR ^= 0)
.CURSOR=NNTDYNA
.CSRPOS=&NNTCSR
)PROC
&NNTLVL = LVLINE(NNTDYNA)
VPUT (NNTS) PROFILE
)END
./ ADD NAME=NNMDBOGG,SSI=01050050
)ATTR DEFAULT(%+_)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)
| AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
01 TYPE(DATAOUT) INTENS(LOW)
02 TYPE(DATAOUT) INTENS(HIGH)
03 TYPE(DATAIN) INTENS(LOW)
04 TYPE(DATAIN) INTENS(HIGH)
)BODY EXPAND(``)
%-`-`- Unknown Newsgroups (found in NEWSRC but not by server) -`-`-
%COMMAND ===>^ZCMD %SCROLL ===>_AMT +
+Groups displayed will be deleted from NEWSRC. Scroll up/down to see all.
+Type%K+to keep a group,%D+to delete. %&END+to accept. %QUIT+or%CANCEL+to abort.
-------------------------------------------------------------------------------+
|NNDYNA |
)INIT
.HELP = TNNM
&END = PFK(END)
IF (&AMT = &Z) &AMT = CSR
IF (&NNDB1ST = &Z)
&NNDB1ST = NO
.ALARM = YES
)PROC
VER (&ZCMD,LIST,QUIT,CAN,CANCEL)
&NNLVL = LVLINE(NNDYNA)
)END
./ ADD NAME=NNMDNEWG,SSI=01080002
)ATTR DEFAULT(%+_)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)
| AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
01 TYPE(DATAOUT) INTENS(LOW)
02 TYPE(DATAOUT) INTENS(HIGH)
03 TYPE(DATAIN) INTENS(LOW)
04 TYPE(DATAIN) INTENS(HIGH)
)BODY EXPAND(``)
%-`-`- New Newsgroups -`-`-
%COMMAND ===>^ZCMD %SCROLL ===>_AMT +
+Type%R+to register a newsgroup; %D+to deregister. Scroll up/down to see all.
+Registered group names highlighted. %&END+to accept. %QUIT+or%CANCEL+to abort.
-------------------------------------------------------------------------------+
|NNDYNA |
)INIT
.HELP = TNNM
&END = PFK(END)
IF (&AMT = &Z) &AMT = CSR
IF (&NNDN1ST = &Z)
&NNDN1ST = NO
.ALARM = YES
)PROC
VER (&ZCMD,LIST,QUIT,CAN,CANCEL)
&NNLVL = LVLINE(NNDYNA)
)END
./ ADD NAME=NNMDNG,SSI=01070008
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
~ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
! TYPE(OUTPUT) INTENS(LOW) CAPS(OFF) JUST(RIGHT) COLOR(YELLOW)
# TYPE(OUTPUT) INTENS(LOW) CAPS(OFF) JUST(RIGHT) COLOR(BLUE)
@ TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT) COLOR(PINK)
? TYPE(OUTPUT) INTENS(LOW) CAPS(OFF) JUST(LEFT) COLOR(TURQ) PAD('.')
| AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
\ AREA(DYNAMIC) EXTEND(OFF) SCROLL(OFF)
01 TYPE(DATAOUT) INTENS(LOW)
02 TYPE(DATAOUT) INTENS(HIGH)
03 TYPE(DATAIN) INTENS(LOW)
04 TYPE(DATAIN) INTENS(HIGH)
05 TYPE(DATAOUT) COLOR(GREEN)
06 TYPE(DATAOUT) COLOR(PINK)
07 TYPE(DATAOUT) COLOR(RED)
08 TYPE(DATAOUT) COLOR(TURQ)
09 TYPE(DATAOUT) COLOR(YELLOW)
0A TYPE(DATAIN) COLOR(BLUE)
0B TYPE(DATAIN) COLOR(PINK)
0C TYPE(DATAIN) COLOR(TURQ)
0D TYPE(DATAIN) COLOR(WHITE)
0E TYPE(DATAIN) COLOR(YELLOW)
)BODY EXPAND(``)
%&NNGHEAD
%COMMAND ===>~NNGCMD %SCROLL ===>^NNGS+
+
\NNGLINE \
-------------------------------------------------------------------------------
|NNGDYNA |
)INIT
.HELP = TNNMG
IF (&NNGS = &Z) &NNGS = CSR
IF (&NNGCSR ^= 0)
.CURSOR=NNGDYNA
.CSRPOS=&NNGCSR
)PROC
&NNGLVL = LVLINE(NNGDYNA)
VPUT (NNGS) PROFILE
)END
./ ADD NAME=NNMLADDG,SSI=01020000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
@ TYPE(OUTPUT) INTENS(LOW)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+
Adding newsgroup:
% &NNLGROUP
+
(Estimated number of articles...&NNLCOUNT)
+ @NNDUMMY
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLADD2,SSI=01010017
)ATTR DEFAULT(|+_)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
/ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
* AREA(DYNAMIC)
)BODY EXPAND(``)
|-`-`- MVS Network News Connection -`-`-
+
Now adding newsgroups
+
Percentage of news groups processed:
------------------------------------------------------------
*NNMBAR *|&NNMCOUNT
+ ------------------------------------------------------------
0% 50% 100%
This may take a long time, depending on the number of newsgroups.
| Please wait.
)INIT
)PROC
)END
./ ADD NAME=NNMLADD3,SSI=01000012
)ATTR DEFAULT(|+_)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
/ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
* AREA(DYNAMIC)
)BODY EXPAND(``)
|-`-`- MVS Network News Connection -`-`-
+
Now adding newsgroup:
|&NNLGROUP
+
Percentage of news groups processed:
------------------------------------------------------------
*NNMBAR *|&NNMCOUNT
+ ------------------------------------------------------------
0% 50% 100%
This may take a long time, depending on the number of newsgroups.
| Please wait.
)INIT
)PROC
)END
./ ADD NAME=NNMLARTS,SSI=01030000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+
Now retrieving the titles of the articles in newsgroup:
% &NNGROUP
+
This may take a long time, depending on the number of articles.
+
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLART2,SSI=01020035
)ATTR DEFAULT(|+_)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
/ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
* AREA(DYNAMIC)
$ TYPE(TEXT) INTENS(LOW)
# TYPE(OUTPUT) INTENS(HIGH)
)BODY EXPAND(``)
|-`-`- MVS Network News Connection -`-`-
+
Now retrieving the titles of the articles in newsgroup:
|&NNGROUP
+
&MSG
+ ------------------------------------------------------------
*NNMBAR *|&TODO
+ ------------------------------------------------------------
0% 50% 100%
$Estimated time to completion:#NNMESTM +
This may take a long time, depending on the number of articles.
| Please wait.
)INIT
IF (&NNMESTM = &Z)
.ATTRCHAR($) = 'INTENS(NON)'
.ATTRCHAR(#) = 'INTENS(NON)'
IF (&NNMCOUNT = -1)
&TODO = &Z
&MSG = 'Articles processed so far while searching:'
ELSE
&TODO = &NNMCOUNT
&MSG = 'Percentage of articles processed so far:'
)PROC
)END
./ ADD NAME=NNMLCONN,SSI=01030000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+ Client name: &NNCLIENT Client IP address: &NNCLIEIP
+
+
+ Connection is in progress for news server at:
&NNSERVER (&NNSERVIP)
+
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLDISC,SSI=01050000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+
+ Disconnection is in progress from the news server at:
&NNSOLDER (&NNSOLDIP)
+
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLEXN2,SSI=01010000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+Newsgroup: &NNLGROUP
+
+Article #:%&NNTNUM
+Subject: &NNTSUBJ
+
+Extracting to: &NNEXDSN
+&MEMSTUFF
+
% Please wait.
+
)INIT
IF (&NNEXMEM = &Z) &MEMSTUFF = &Z
ELSE &MEMSTUFF = 'Member: &NNEXMEM'
)PROC
)END
./ ADD NAME=NNMLLIST,SSI=01030000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+
A list of all newsgroups is being retrieved from the news server at:
&NNSERVER (&NNSERVIP)
+
This may take a long time, depending on the number of newsgroups known.
+
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLNEWG,SSI=01000032
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+
A list of new newsgroups since &NNNGDT &NNNGTM is being retrieved
+ from the news server at: &NNSERVER (&NNSERVIP)
+
This may take a long time, depending on the number of newsgroups known.
+
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLPRN2,SSI=01010059
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+Newsgroup: &NNLGROUP
+
+Article #:%&NNTNUM
+Subject: &NNTSUBJ
+
+Printing to SYSOUT class: &NNEXSCL
+&MEMSTUFF
+
% Please wait.
+
)INIT
IF (&NNEXMEM = &Z) &MEMSTUFF = &Z
ELSE &MEMSTUFF = 'Member: &NNEXMEM'
)PROC
)END
./ ADD NAME=NNMLRCON,SSI=01020000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+Connection has apparently been lost to the news server at:
&NNSERVER (&NNSERVIP)
+
+Reconnection to the server is in progress.
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLRETG,SSI=01010000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+
Retrieving current status of newsgroup:
% &NNLGROUP
+
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLRET2,SSI=01000019
)ATTR DEFAULT(|+_)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
/ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
* AREA(DYNAMIC)
$ TYPE(TEXT) INTENS(LOW)
# TYPE(OUTPUT) INTENS(HIGH)
)BODY EXPAND(``)
|-`-`- MVS Network News Connection -`-`-
+
+
+ Retrieving current status of registered newsgroups
+
+
+ Percentage of registered newsgroups processed:
+ ------------------------------------------------------------
+ *NNMBAR *|&NNMCOUNT
+ ------------------------------------------------------------
+ 0% 50% 100%
+
+ $Estimated time to completion:#NNMESTM +
+
)INIT
IF (&NNMESTM = &Z)
.ATTRCHAR($) = 'INTENS(NON)'
.ATTRCHAR(#) = 'INTENS(NON)'
)PROC
)END
./ ADD NAME=NNMLRET3,SSI=01000044
)ATTR DEFAULT(|+_)
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
/ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
* AREA(DYNAMIC)
$ TYPE(TEXT) INTENS(LOW)
# TYPE(OUTPUT) INTENS(HIGH)
)BODY EXPAND(``)
|-`-`- MVS Network News Connection -`-`-
+
+
+ Retrieving current status of newsgroup:
| &NNLGROUP
+
+ Percentage of registered newsgroups processed:
+ ------------------------------------------------------------
+ *NNMBAR *|&NNMCOUNT
+ ------------------------------------------------------------
+ 0% 50% 100%
+
+ $Estimated time to completion:#NNMESTM +
+
)INIT
IF (&NNMESTM = &Z)
.ATTRCHAR($) = 'INTENS(NON)'
.ATTRCHAR(#) = 'INTENS(NON)'
)PROC
)END
./ ADD NAME=NNMLRSNG,SSI=01020000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+ Reconnection has been established to the news server at:
&NNSERVER (&NNSERVIP)
+
Now reestablishing current newsgroup:
% &NNGROUP
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMLUNRC,SSI=01000004
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Connection -`-`-
+
+
+ Updating NEWSRC file &NNNEWSRF ...
+
+
+
% Please wait.
+
+
)INIT
)PROC
)END
./ ADD NAME=NNMOPTS,SSI=010B0035
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
)BODY EXPAND(``)
%-`-`- NNMVS - Article Retrieval Options -`-`-
%Command ===>_ZCMD
+
%General options:
+In-progress screen for adding newsgroups? (YES/NO)%==>_Z +
+In-progress screen for rewriting NEWSRC? (YES/NO)%==>_Z +
+In-progress screen for retrieving articles?(YES/NO)%==>_Z +
+Screen update frequency %==>_Z + (Enter%ON, OFF,+or%number+of seconds)
%EXTRACT prompting options:
+Warning panel before writing over an existing dataset?%==>_Z +
+Warning panel before appending to an existing dataset?%==>_Z +
+Press%ENTER+to change options. Press%&END+(or type%END+command) when done.
)INIT
.ZVARS = '(NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP)'
.HELP = TNNMOPT
.CURSOR = ZCMD
&END = PFK(END)
&ZCMD = &Z
VGET (NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP) PROFILE
IF (&NNMUPDTF = &Z) &NNMUPDTF = '5'
&NNUPAN = TRANS(TRUNC(&NNUPAN,1) Y,YES N,NO *,NO )
&NNUPRN = TRANS(TRUNC(&NNUPRN,1) Y,YES N,NO *,YES)
&NNUPRA = TRANS(TRUNC(&NNUPRA,1) Y,YES N,NO *,YES)
&NNEXTPOW = TRANS(TRUNC(&NNEXTPOW,1) Y,YES N,NO *,YES)
&NNEXTPAP = TRANS(TRUNC(&NNEXTPAP,1) Y,YES N,NO *,YES)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
IF (.RESP = ENTER)
VER(&NNMUPDTF,NB)
IF (&NNMUPDTF = '0') &NNMUPDTF = 'ON'
IF (&NNMUPDTF = 'ON','OFF')
ELSE
VER(&NNMUPDTF,NUM)
&NNUPAN = TRUNC(&NNUPAN,1)
&NNUPRN = TRUNC(&NNUPRN,1)
&NNUPRA = TRUNC(&NNUPRA,1)
&NNEXTPOW = TRUNC(&NNEXTPOW,1)
&NNEXTPAP = TRUNC(&NNEXTPAP,1)
VER(&NNUPAN ,NB,LIST,Y,N)
VER(&NNUPRN ,NB,LIST,Y,N)
VER(&NNUPRA ,NB,LIST,Y,N)
VER(&NNEXTPOW,NB,LIST,Y,N)
VPUT (NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP) PROFILE
)END
./ ADD NAME=NNMOPTT,SSI=01030057
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
)BODY EXPAND(``)
%-`-`- NNMVS - Table Viewing Options -`-`-
%Command ===>_ZCMD
+
%Newsgroup table options:
+Scroll last selected newsgroup to top? (YES/NO)%==>_Z +
+Put cursor at last selected newsgroup? (YES/NO)%==>_Z +
%Article table options:
+Scroll last selected article to top? (YES/NO)%==>_Z +
+Put cursor at last selected article? (YES/NO)%==>_Z +
+Number of heading rows to display per article %==>_Z+ (Enter%1, 2+or%3+only)
+Press%ENTER+to change options. Press%&END+(or type%END+command) when done.
)INIT
.ZVARS = '(NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS)'
.HELP = TNNMOPT
.CURSOR = ZCMD
&END = PFK(END)
&ZCMD = &Z
VGET (NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS) PROFILE
&NNNGSCR = TRANS(TRUNC(&NNNGSCR,1) Y,YES N,NO *,YES)
&NNNGCSR = TRANS(TRUNC(&NNNGCSR,1) Y,YES N,NO *,NO)
&NNARSCR = TRANS(TRUNC(&NNARSCR,1) Y,YES N,NO *,YES)
&NNARCSR = TRANS(TRUNC(&NNARCSR,1) Y,YES N,NO *,NO)
&NNARROWS = TRANS(&NNARROWS 1,1 2,2 3,3 *,1)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
IF (.RESP = ENTER)
&NNNGSCR = TRUNC(&NNNGSCR,1)
&NNNGCSR = TRUNC(&NNNGCSR,1)
&NNARSCR = TRUNC(&NNARSCR,1)
&NNARCSR = TRUNC(&NNARCSR,1)
VER(&NNNGSCR,NB,LIST,Y,N)
VER(&NNNGCSR,NB,LIST,Y,N)
VER(&NNARSCR,NB,LIST,Y,N)
VER(&NNARCSR,NB,LIST,Y,N)
VER(&NNARROWS,NB,LIST,1,2,3)
VPUT (NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS) PROFILE
)END
./ ADD NAME=NNMPAUTH,SSI=01050017
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
)BODY WINDOW(62,14)
+
%Command ===>_ZCMD
+
NNMVS could not obtain authorization from the NNTP server.
You may proceed, but you should be aware that some news
reading or posting operations may fail.
The response from server &NNSERVER was:
%&NNSRVRSP
+
Press%ENTER+to proceed.
Press%END +to return to the NNMVS primary menu.
)INIT
.HELP = TNNM
&ZWINTTL = 'Server authorization failed'
&END = PFK(END)
&ZCMD = &Z
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
)END
./ ADD NAME=NNMPCAN,SSI=01000015
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(64,14)
+
%Command ===>^ZCMD
+
+Newsgroup :%&NNCGROUP
+Article: %&NNCNUM
+Message-ID:%&NNCMSGID
+Subject: %&NNCSUBJ
+This action will forward a CANCEL request to the news server.
+
+Press%ENTER+to proceed to cancel this article.
+
+Press%&END (END)+to abandon the request and leave the article.
)INIT
.HELP = TNNM
&ZWINTTL = 'Confirm Article Cancellation'
&END = PFK(END)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
)END
./ ADD NAME=NNMPCONM,SSI=01040055
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
)BODY WINDOW(49,10)
+
%Command ===>_ZCMD
+To: %&NNMAILTO
+Subject:%&NNMAILSJ
+Press%ENTER +to mail this message.
+Press%&END (END)+to return to the mail menu.
+Enter%CANCEL +to cancel the message.
)INIT
.HELP = TNNM
&ZWINTTL = 'Confirm mailing'
&END = PFK(END)
&ZCMD = &Z
)PROC
VER(&ZCMD,LIST,CAN,CANCEL)
)END
./ ADD NAME=NNMPCONP,SSI=01040000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
)BODY WINDOW(49,10)
+
%Command ===>_ZCMD
+Newsgroups:%&NNPOSTNG
+Subject: %&NNPOSTSJ
+Press%ENTER +to post this article.
+Press%&END (END)+to return to the posting menu.
+Enter%CANCEL +to cancel the post.
)INIT
.HELP = TNNM
&ZWINTTL = 'Confirm posting'
&END = PFK(END)
&ZCMD = &Z
)PROC
VER(&ZCMD,LIST,CAN,CANCEL)
)END
./ ADD NAME=NNMPEXDS,SSI=01150041
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,16)
+
%Command ===>^ZCMD
+
+&NUMBER %&SUBJECT
+
+Save to data set ===>_NNEXDSN
+Expand tab characters? ===>_Z +
+(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
+Append to end of data set? ===>_Z +
+Blank line after separator? ===>_Z +
+Separator line between articles (append mode only...blank for none):
+>^Z +<
+Press%&END (END)+to cancel the extract request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXTAB NNEXAPP NNEXBLK NNEXSEP)'
.CURSOR = NNEXDSN
IF (&NNTNUM ^= &Z)
&ZWINTTL = 'Extract from &NNGROUP'
&NUMBER = 'Article &NNTNUM: '
&SUBJECT = '&NNTSUBJ'
ELSE
&ZWINTTL = 'Extract text'
&NUMBER = ' '
&SUBJECT = ' '
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXDSN NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
&NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
&NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
&NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXDSN,NB,DSNAME)
&NNEXTAB = TRUNC(&NNEXTAB,1)
VER(&NNEXTAB,NB,LIST,Y,N)
&NNEXAPP = TRUNC(&NNEXAPP,1)
VER(&NNEXAPP,NB,LIST,Y,N)
&NNEXBLK = TRUNC(&NNEXBLK,1)
VER(&NNEXBLK,NB,LIST,Y,N)
VPUT (NNEXDSN NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
)END
./ ADD NAME=NNMPEXNG,SSI=01040050
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,14)
+
%Command ===>^ZCMD
+
+Save to data set ===>_NNEXDSN
+(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
+Append to end of data set? ===>_Z +
+Blank line after separator? ===>_Z +
+Separator line between articles (append mode only...blank for none):
+>^Z +<
+Press%&END (END)+to cancel the extract request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXAPP NNEXBLK NNEXSEP)'
.CURSOR = NNEXDSN
&ZWINTTL = 'Extract newsgroup listing'
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
&NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
&NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXDSN,NB,DSNAME)
&NNEXAPP = TRUNC(&NNEXAPP,1)
VER(&NNEXAPP,NB,LIST,Y,N)
&NNEXBLK = TRUNC(&NNEXBLK,1)
VER(&NNEXBLK,NB,LIST,Y,N)
VPUT (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
)END
./ ADD NAME=NNMPEXNP,SSI=01060057
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY EXPAND(``) WINDOW(77,14)
+
%Command ===>^ZCMD
+
+Data set name%===>_NNEXPDS
+Member prefix%===>_NNEXPMP + (article number appended - default is%#+)
+Note: The dataset must be a PDS (old or new) with RECFM=VB and LRECL=259.
+Expand tab characters? %===>_Z +
+From article number%===>_NNEXAN1 + (blank for first article in table)
+To article number%===>_NNEXAN2 + (blank for last article in table)
+Press%&END (END)+to cancel the extract request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXTAB)'
.CURSOR = ZCMD
&ZWINTTL = 'Log text of articles in &NNGROUP to PDS members'
&NUMBER = ' &NNTNUM: '
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXPDS NNEXPMP NNEXTAB) PROFILE
&NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
IF (&NNEXPMP = &Z) &NNEXPMP = '#'
&NNEXAN1 = &Z
&NNEXAN2 = &Z
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
&NNEXTAB = TRUNC(&NNEXTAB,1)
VER(&NNEXTAB,NB,LIST,Y,N)
VER(&NNEXPDS,NB,DSNAME)
&TEMP1 = TRUNC(&NNEXPDS,1)
&TEMP2 = .TRAIL
IF (&TEMP1 = '''')
&NNEXDSN = TRUNC(&TEMP2,'''')
ELSE
&NNEXDSN = '&ZPREFIX..&NNEXPDS'
VER(&NNEXPMP,NB,NAME)
VER(&NNEXAN1,NUM)
VER(&NNEXAN2,NUM)
VPUT (NNEXPDS NNEXPMP NNEXTAB) PROFILE
)END
./ ADD NAME=NNMPEXNS,SSI=01050005
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY EXPAND(``) WINDOW(77,17)
+
%Command ===>^ZCMD
+
+Data set name%===>_NNEXSEQ
+(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
+
+Expand tab characters? %===>_Z +
+
+Append to end of data set? %===>_Z +
+Blank line after separator? %===>_Z +
+Separator line before each article (leave blank for none):
+>^Z +<
+From article number%===>_NNEXAN1 + (blank for first article in table)
+To article number%===>_NNEXAN2 + (blank for last article in table)
+Press%&END (END)+to cancel the extract request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXTAB NNEXAPP NNEXBLK NNEXSEP)'
.CURSOR = ZCMD
&ZWINTTL = 'Log text of articles in &NNGROUP to sequential file'
&NUMBER = ' &NNTNUM: '
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXSEQ NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
&NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
&NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
&NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
&NNEXAN1 = &Z
&NNEXAN2 = &Z
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXSEQ,NB,DSNAME)
&NNEXDSN = &NNEXSEQ
&NNEXTAB = TRUNC(&NNEXTAB,1)
VER(&NNEXTAB,NB,LIST,Y,N)
&NNEXAPP = TRUNC(&NNEXAPP,1)
VER(&NNEXAPP,NB,LIST,Y,N)
&NNEXBLK = TRUNC(&NNEXBLK,1)
VER(&NNEXBLK,NB,LIST,Y,N)
VER(&NNEXAN1,NUM)
VER(&NNEXAN2,NUM)
VPUT (NNEXSEQ NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
)END
./ ADD NAME=NNMPEXNT,SSI=01060013
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,10)
+
%Command ===>^ZCMD
+
+Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
+
_A%1+- List%titles+of articles in table
_B%2+- Log %text +of articles to%sequential file+
_C%3+- Log %text +of articles to%members of PDS+
+
+Press%&END (END)+to cancel the extract request.
)INIT
.HELP = TNNM
.CURSOR = ZCMD
&ZWINTTL = 'Extract news articles - titles or text'
&END = PFK(END)
&ZCMD = &Z
&A = &Z
&B = &Z
&C = &Z
)PROC
VER(&ZCMD,LIST,1,2,3)
IF (&ZCMD ^= &Z)
&NNCHOICE = TRANS(&ZCMD 1 1 2 2 3 3 * ?)
ELSE
&TEMP = '&A/&B/&C'
IF (&TEMP = '//')
&NNCHOICE = TRANS(.CURSOR A 1 B 2 C 3 * ?)
ELSE
&NNCHOICE = TRANS(&TEMP 'S//' 1
'1//' 1
'/S/' 2
'/2/' 2
'//S' 3
'//3' 3
* ?
)
)END
./ ADD NAME=NNMPEXN1,SSI=01030021
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,14)
+
%Command ===>^ZCMD
+
+Save to data set ===>_NNEXDSN
+(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
+Append to end of data set? ===>_Z +
+Blank line after separator? ===>_Z +
+Separator line between articles (append mode only...blank for none):
+>^Z +<
+Press%&END (END)+to cancel the extract request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXAPP NNEXBLK NNEXSEP)'
.CURSOR = NNEXDSN
&ZWINTTL = 'Extract news article listing'
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
&NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
&NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXDSN,NB,DSNAME)
&NNEXAPP = TRUNC(&NNEXAPP,1)
VER(&NNEXAPP,NB,LIST,Y,N)
&NNEXBLK = TRUNC(&NNEXBLK,1)
VER(&NNEXBLK,NB,LIST,Y,N)
VPUT (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
)END
./ ADD NAME=NNMPEXOW,SSI=01020028
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(58,10)
+
%Command ===>^ZCMD
+
+Dataset already exists:
+
%&NNEXDSN
+
+Press%ENTER+to%&ACTION
+Press%&END (END)+to cancel the request.
+
)INIT
.HELP = TNNM
.ALARM = YES
&ZWINTTL = 'Extract To Existing Data Set'
&END = PFK(END)
&APP = TRUNC(&NNEXAPP,1)
IF (&APP = Y) &ACTION = 'append to the end of the data set.'
ELSE &ACTION = 'overwrite the current data set.'
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
)END
./ ADD NAME=NNMPEXPW,SSI=01020035
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(58,13)
+
%Command ===>^ZCMD
+
+Partitioned dataset already exists:
+
%&NNEXDSN
+
+If member names are generated that match existing members
+of this PDS, they will be%overwritten.+
+
+Press%ENTER+to proceed to use this PDS.
+Press%&END (END)+to cancel the request.
+
)INIT
.HELP = TNNM
.ALARM = YES
&ZWINTTL = 'Extract To Members of Existing PDS'
&END = PFK(END)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
)END
./ ADD NAME=NNMPGAUT,SSI=01010012
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
@ TYPE(INPUT) INTENS(NON) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(64,14)
+
%Command ===>^ZCMD
+
+The NNTP server at &NNSERVER
+requires authorization to perform this operation.
+
+Username (as known to NNTP server) ===>^NNAUSER
+Password (as known to NNTP server) ===>@NNAPASS
+
+Press%&END (END)+to abort the current request.
)INIT
.HELP = TNNM
&ZWINTTL = 'Server Authorization Required'
&NNAPASS = &Z
&END = PFK(END)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNAUSER,NB)
VER(&NNAPASS,NB)
VPUT (NNAUSER) PROFILE
)END
./ ADD NAME=NNMPGREG,SSI=01060042
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(58,10)
+
%Command ===>^ZCMD
+
+Get current status of each newsgroup in your list?
+(If you answer YES, it will take longer to start up.)
+(If you answer NO, displayed status will be incomplete.)
+
%===>_Z +
+Press%&END (END)+to return to the previous panel.
)INIT
.HELP = TNNM
.ZVARS = '(NNRGANS)'
.CURSOR = NNRGANS
&ZWINTTL = ''
&END = PFK(END)
&NNRGANS = Y
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
&NNRGANS = TRUNC(&NNRGANS,1)
VER(&NNRGANS,NB,LIST,Y,N)
)END
./ ADD NAME=NNMPMALL,SSI=01010044
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(76,14)
+
%Command ===>^ZCMD
+
+Newsgroup:%&NNGNAME
+
+What exactly do you want to do?
+
_Z%*+Mark%all+articles in the newsgroup &NNMARK
_Z%*+Mark%currently displayed+articles &NNMARK
_Z%*+Cancel this request and return to previous panel
+Move cursor to choice (or type%S+next to choice) and press%ENTER+to do it.
+
+Press%&END (END)+to cancel the request.
)INIT
.HELP = TNNM
.ZVARS = '(S1 S2 S3)'
.CURSOR = ZCMD
&ZWINTTL = 'Confirm Marking All Articles in Newsgroup'
&END = PFK(END)
&ZCMD = &Z
&S1 = &Z
&S2 = &Z
&S3 = &Z
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
&TEMP = '&S1/&S2/&S3'
IF (&TEMP = '//')
&NNCHOICE = TRANS(.CURSOR S1 1 S2 2 S3 3 * ?)
ELSE
&NNCHOICE = TRANS(&TEMP 'S//' 1
'1//' 1
'/S/' 2
'/2/' 2
'//S' 3
'//3' 3
* ?
)
)END
./ ADD NAME=NNMPMARK,SSI=01030048
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(58,10)
+
%Command ===>^ZCMD
+
+Newsgroup:%&NNGNAME
+
+Be sure you really want to mark all articles%&NNMARK..
+
+Press%ENTER+to proceed with marking all articles.
+
+Press%&END (END)+to cancel the request.
)INIT
.HELP = TNNM
&ZWINTTL = 'Confirm Marking All Articles in Newsgroup'
&END = PFK(END)
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
)END
./ ADD NAME=NNMPOPT,SSI=01050056
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,11)
+
%Command ===>^ZCMD
+
+Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
+
_Z%1+- RFC822 header display options
_Z%2+- Article retrieval options
_Z%3+- Table processing options
+
+Press%&END (END)+to return to the previous panel.
)INIT
.HELP = TNNMOPT
.ZVARS = '(S1 S2 S3)'
.CURSOR = ZCMD
&ZWINTTL = 'Customize user options'
&END = PFK(END)
&ZCMD = &Z
&S1 = &Z
&S2 = &Z
&S3 = &Z
)PROC
IF (&ZCMD ^= &Z)
&NNCHOICE = TRANS(&ZCMD 1 1 2 2 3 3 * ?)
ELSE
&TEMP = '&S1/&S2/&S3'
IF (&TEMP = '//')
&NNCHOICE = TRANS(.CURSOR S1 1 S2 2 S3 3 * ?)
ELSE
&NNCHOICE = TRANS(&TEMP 'S//' 1
'1//' 1
'/S/' 2
'/2/' 2
'//S' 3
'//3' 3
* ?
)
)END
./ ADD NAME=NNMPPRNT,SSI=01010028
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,9)
+
%Command ===>^ZCMD
+
+Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
+
_A%1+- Print%titles+of articles in table
_B%2+- Print%text +of articles
+
+Press%&END (END)+to cancel the print request.
)INIT
.HELP = TNNM
.CURSOR = ZCMD
&ZWINTTL = 'Print news articles - titles or text'
&END = PFK(END)
&ZCMD = &Z
&A = &Z
&B = &Z
)PROC
VER(&ZCMD,LIST,1,2)
IF (&ZCMD ^= &Z)
&NNCHOICE = TRANS(&ZCMD 1 1 2 2 * ?)
ELSE
&TEMP = '&A/&B'
IF (&TEMP = '/')
&NNCHOICE = TRANS(.CURSOR A 1 B 2 * ?)
ELSE
&NNCHOICE = TRANS(&TEMP 'S/' 1
'1/' 1
'/S' 2
'/2' 2
* ?
)
)END
./ ADD NAME=NNMPPRT,SSI=01050002
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
~ TYPE(TEXT) INTENS(HIGH)
\ TYPE(TEXT) INTENS(LOW)
{ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
} TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)
# TYPE(TEXT) INTENS(LOW)
@ TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)
)BODY WINDOW(77,19)
+
%Command ===>^ZCMD
+
+&NUMBER %&SUBJECT
+
+SYSOUT class ===>_Z+ Number of copies ===>_Z +
#Destination ===>@Z # Forms ===>@Z # UCS ===>@Z +
+(Note: Print data will be released to SYSOUT immediately.)
+
\Page eject between articles? ~===>}Z +
\Blank line after separator? ~===>}Z +
\Separator line before each article (leave blank for none):
\>{Z \<
\From article number~===>}NNEXAN1 \ (blank for first article in table)
\To article number~===>}NNEXAN2 \ (blank for last article in table)
+Press%&END (END)+to cancel the print request.
)INIT
.HELP = TNNM
.ZVARS =
'(NNEXSCL NNEXSCO NNEXSDE NNEXSFO NNEXSUC NNEXSPA NNEXBLK NNEXSEP)'
.CURSOR = NNEXSCL
&END = PFK(END)
&ZCMD = &Z
&NNEXSCO = 1
&PVARS = 'NNEXSCL'
IF (&NNALLPR ^= &Z)
&PVARS = '&PVARS NNEXSDE NNEXSFO NNEXSUC'
.ATTRCHAR('#') = 'TYPE(TEXT) INTENS(LOW)'
.ATTRCHAR('@') = 'TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)'
ELSE
.ATTRCHAR('#') = 'TYPE(TEXT) INTENS(NON)'
.ATTRCHAR('@') = 'TYPE(OUTPUT) INTENS(NON)'
IF (&NNWHICH = NNMPPRNS)
.ATTRCHAR('~') = 'TYPE(TEXT) INTENS(HIGH)'
.ATTRCHAR('\') = 'TYPE(TEXT) INTENS(LOW)'
.ATTRCHAR('{') = 'TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)'
.ATTRCHAR('}') = 'TYPE(INPUT) INTENS(HIGH) CAPS(ON) JUST(LEFT)'
ELSE
.ATTRCHAR('~') = 'TYPE(TEXT) INTENS(NON)'
.ATTRCHAR('\') = 'TYPE(TEXT) INTENS(NON)'
.ATTRCHAR('{') = 'TYPE(OUTPUT) INTENS(NON)'
.ATTRCHAR('}') = 'TYPE(OUTPUT) INTENS(NON)'
IF (&NNWHICH = NNMPPRNG)
&ZWINTTL = 'Print newsgroup listing'
IF (&NNWHICH = NNMPPRN1)
&ZWINTTL = 'Print news article listing'
IF (&NNWHICH = NNMPPRDS)
IF (&NNTNUM ^= &Z)
&ZWINTTL = 'Print from &NNGROUP'
&NUMBER = 'Article &NNTNUM: '
&SUBJECT = '&NNTSUBJ'
ELSE
&ZWINTTL = 'Print text'
&NUMBER = &Z
&SUBJECT = &Z
ELSE
&NUMBER = &Z
&SUBJECT = &Z
IF (&NNWHICH = NNMPPRNS)
&PVARS = '&PVARS NNEXSPA NNEXBLK NNEXSEP'
&ZWINTTL = 'Print text of articles in &NNGROUP'
&NNEXSPA = TRANS(TRUNC(&NNEXSPA,1) Y,YES N,NO ' ',NO)
&NNEXBLK = TRANS(TRUNC(&NNEXBLK,1) Y,YES N,NO ' ',NO)
&NNEXSCO = 1
&NNEXAN1 = &Z
&NNEXAN2 = &Z
VGET (&PVARS) PROFILE
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXSCL,NB)
IF (&NNEXSCO = &Z) &NNEXSCO = 1
VER(&NNEXSCO,NUM)
VER(&NNEXSCO,RANGE,1,255)
IF (&NNWHICH = NNMPPRNS)
&NNEXSPA = TRUNC(&NNEXSPA,1)
&NNEXBLK = TRUNC(&NNEXBLK,1)
VER(&NNEXSPA,NB,LIST,Y,N)
VER(&NNEXBLK,NB,LIST,Y,N)
VER(&NNEXAN1,NUM)
VER(&NNEXAN2,NUM)
VPUT (&PVARS) PROFILE
)END
./ ADD NAME=NNMQMAIL,SSI=01080000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY EXPAND(``)
-`-`- Send a mail message or reply -`-`-
%Command ===>^ZCMD
+
%Note:+This sends private mail to the individual sender named below.
+To transmit to the newsgroup, use the%POST+command, or use
+the%F (FOLLOWUP)+selection code.+
+
+&HEADING
%Required Header Fields+
+Mail to ===>^NNMAILTO
+Subject ===>^NNMAILSJ
%Optional Header Fields+
+Reply to ==>^NNMAILRT
+Your human name ==>^NNMAILFR
+Signature file ==>_NNMAILSF
+Edit profile ==>_NNEDPROF+
+Press%ENTER+to proceed to the editor to compose the message.
+Press%&END (END)+to cancel the mailing request.
)INIT
.HELP = TNNM
IF (&NNMAILOT = &Z) &HEADING = 'New mail message'
ELSE &HEADING = 'Reply to message from &NNMAILOT'
IF (&NNMAILTO = &Z) .CURSOR = NNMAILTO
ELSE .CURSOR = NNMAILSJ
&ZWINTTL = 'Send a mail message or reply'
&END = PFK(END)
&ZCMD = &Z
IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
/* IF (&NNMAILSF = &Z) &NNMAILSF = &NNPOSTSF */
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNMAILTO,NB)
VER(&NNMAILSJ,NB)
VER(&NNMAILSF,DSNAME)
VER(&NNEDPROF,NAME)
IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
VPUT (NNMAILRT NNMAILFR NNMAILSF NNEDPROF) PROFILE
)END
./ ADD NAME=NNMQPOST,SSI=01040000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
/* /*
/* There seems to be some kind of bug in ISPF 3.3. Substitution of /*
/* variables is not done before the first input field, so I could /*
/* not put the panel heading where I wanted it. ??? /*
/* /*
)BODY EXPAND(``)
-`-`- Post to news server -`-`-
%Command ===>^ZCMD
%Note:+The fate of a posted news article is determined by the%news server+
%(&NNSERVER).
+Posting: &HEADING
%Required Header Fields+
+Newsgroups ===>^NNPOSTNG
+Subject ===>^NNPOSTSJ
%Optional Header Fields+
+Reply To ==>^NNPOSTRT
+Followup To ==>^NNPOSTFO
+Your human name ==>^NNPOSTFR
+Signature file ==>_NNPOSTSF
+Edit profile ==>_NNEDPROF+
+Press%ENTER+to proceed to the editor to compose the article.
+Press%&END (END)+to cancel the posting request.
)INIT
.HELP = TNNM
IF (&NNPOSTHA = &Z)
&HEADING = 'New Article'
ELSE
&HEADING = 'Followup to Article &NNPOSTHA in group &NNPOSTHG'
IF (&NNPOSTNG = &Z) .CURSOR = NNPOSTNG
ELSE .CURSOR = NNPOSTSJ
&END = PFK(END)
&ZCMD = &Z
IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
/* IF (&NNPOSTSF = &Z) &NNPOSTSF = &NNMAILSF */
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNPOSTNG,NB)
VER(&NNPOSTSJ,NB)
VER(&NNPOSTSF,DSNAME)
VER(&NNEDPROF,NAME)
IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
VPUT (NNPOSTRT NNPOSTFR NNPOSTSF NNEDPROF) PROFILE
)END
./ ADD NAME=NNMRCERR,SSI=01050000
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Viewer -`-`-
%COMMAND ===>_ZCMD
+
% ` ` *** ERROR *** ` ` +
+
% ` ` Unable to access the NEWSRC file, which is required. ` ` +
+
+ ` ` This file must be allocated to DDname%NNNEWSRC. ` ` +
+
+ ` ` The News Viewer cannot continue. ` ` +
+
+
+ ` ` Press!ENTER+or!END+key to leave this panel. ` ` +
)INIT
.HELP = TNNM
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
)END
./ ADD NAME=NNMRFCH,SSI=01030029
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
! TYPE(TEXT) INTENS(LOW)
? TYPE(TEXT) INTENS(LOW)
{ TYPE(TEXT) INTENS(LOW)
} TYPE(TEXT) INTENS(LOW)
)BODY EXPAND(``)
%-`-`- NNMVS - RFC822 Header Viewing Options -`-`-
%Command ===>_ZCMD
+
+The current RFC822 header viewing option is highlighted.
+Move cursor to choice (or type%S+next to choice) and press%ENTER+to change:
+
_A!Show all RFC822 headers
_B?Show all RFC822 headers except those in Exclude List
_C{Show the RFC822 headers in Include List only
_D}Suppress RFC822 headers entirely
+
+Lists are header names separated by blanks. Do%not+put%:+in header names.
+
%Include List ==>_NNRFCINC
%Exclude List ==>_NNRFCEXC
+Press%ENTER+to change options. Press%&END+(or type%END+command) when done.
)INIT
.HELP = TNNMOPT
.CURSOR = ZCMD
&END = PFK(END)
&ZCMD = &Z
&A = &Z
&B = &Z
&C = &Z
&D = &Z
VGET (NNRFCOPT NNRFCINC NNRFCEXC) PROFILE
IF (&NNRFCOPT = &Z) &NNRFCOPT = A
IF (&NNRFCOPT = A) .ATTRCHAR(!) = 'INTENS(HIGH)'
IF (&NNRFCOPT = B) .ATTRCHAR(?) = 'INTENS(HIGH)'
IF (&NNRFCOPT = C) .ATTRCHAR({) = 'INTENS(HIGH)'
IF (&NNRFCOPT = D) .ATTRCHAR(}) = 'INTENS(HIGH)'
IF (&NNRFCOPT = B) .ATTR(NNRFCEXC) = 'INTENS(HIGH)'
ELSE .ATTR(NNRFCEXC) = 'INTENS(LOW)'
IF (&NNRFCOPT = C) .ATTR(NNRFCINC) = 'INTENS(HIGH)'
ELSE .ATTR(NNRFCINC) = 'INTENS(LOW)'
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
IF (.RESP = ENTER)
&TEMP = '&A/&B/&C/&D'
IF (&TEMP = '///')
&NNCHOICE = TRANS(.CURSOR A A B B C C D D * ' ')
ELSE
&NNCHOICE = TRANS(&TEMP 'S///' A
'/S//' B
'//S/' C
'///S' D
* ? )
IF (&NNCHOICE = '?')
&ZERRSM = 'Invalid choice'
&ZERRLM = 'Make exactly one selection with the cursor or type only one S.'
&ZERRALRM = YES
&ZERRHM = '*'
.MSG = ISRZ002
ELSE
IF (&NNCHOICE ^= &Z)
&NNRFCOPT = &NNCHOICE
VPUT (NNRFCOPT NNRFCINC NNRFCEXC) PROFILE
)END
./ ADD NAME=NNMVIEW,SSI=01030025
)ATTR DEFAULT(%+_)
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
# TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT)
\ TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
| AREA(DYNAMIC) EXTEND(ON) SCROLL(ON) USERMOD(05)
01 TYPE(DATAOUT) INTENS(LOW)
02 TYPE(DATAOUT) INTENS(HIGH)
03 TYPE(DATAIN) INTENS(LOW)
04 TYPE(DATAIN) INTENS(HIGH)
)BODY
\NNBTITLE
%COMMAND ===>^ZCMD %SCROLL ===>_Z +
|NNBDYNA |
)INIT
.ZVARS = NNMARTSC
IF (&NNMARTSC = &Z) &NNMARTSC = CSR
&TNNMTHR = 'NNMVIEW'
.HELP = TNNMB1
.CURSOR = &NNBCUR
.CSRPOS = &NNBPOS
)PROC
&NNBCUR = .CURSOR
&NNBPOS = .CSRPOS
&NNBLVL = LVLINE(NNBDYNA)
VPUT (NNMARTSC) PROFILE
)END
./ ADD NAME=NNM0,SSI=01070048
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
_ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
@ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%-`-`- MVS Network News Client: NNTP Native Protocol Mode -`-`-
%COMMAND ===>_ZCMD
+
%NNTP command ===>_NNCMD
+
+
+Press!END+key to leave this menu.
)INIT
.HELP = TNNM
.CURSOR = NNCMD
&ZCMD = &Z
)PROC
IF (&ZCMD ^= &Z) .MSG=ISPZ001
)END
./ ADD NAME=ONMBROBF,SSI=01000046
)ATTR
/* */
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 */
/* */
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. */
/* */
/* This software is provided on an "AS IS" basis. All warranties, */
/* including the implied warranties of merchantability and fitness, */
/* are expressly denied. */
/* */
/* Provided this copyright notice is included, this software may */
/* be freely distributed and not offered for sale. */
/* */
/* Changes or modifications may be made and used only by the maker */
/* of same, and not further distributed. Such modifications should */
/* be mailed to the author for consideration for addition to the */
/* software and incorporation in subsequent releases. */
/* */
_ TYPE(INPUT) CAPS(OFF) INTENS(HIGH) FORMAT(&MIXED)
+ TYPE(TEXT) INTENS(LOW)
)BODY WIDTH(&ZWIDTH) EXPAND(//)
%BROWSE ----------------------------------/-/----------------------------------+
%COMMAND ===>_ZCMD / / %SCROLL ===>_Z +
)INIT
&TNNMTHR = 'NNMBROBF'
.HELP = TNNMB1
.ZVARS = 'ZSCBR'
&MIXED = MIX /* SET FORMAT MIX */
IF (&ZPDMIX = N) /* IF EBCDIC MODE REQUESTED */
&MIXED = EBCDIC /* SET FORMAT EBCDIC */
)END
/* 5665-402 (C) COPYRIGHT IBM CORP 1980, 1989 */
./ ADD NAME=ONMPPRDS,SSI=01090042
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,11)
+
%Command ===>^ZCMD
+
+&NUMBER %&SUBJECT
+
+SYSOUT class ===>_Z+ Number of copies ===>_Z +
+(Note: Print data will be released to SYSOUT immediately.)
+Press%&END (END)+to cancel the print request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXSCL NNEXSCO)'
.CURSOR = NNEXSCL
IF (&NNTNUM ^= &Z)
&ZWINTTL = 'Print from &NNGROUP'
&NUMBER = 'Article &NNTNUM: '
&SUBJECT = '&NNTSUBJ'
ELSE
&ZWINTTL = 'Print text'
&NUMBER = ' '
&SUBJECT = ' '
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXSCL) PROFILE
&NNEXSCO = 1
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXSCL,NB,NAME)
IF (&NNEXSCO = &Z) &NNEXSCO = 1
VER(&NNEXSCO,NUM)
VER(&NNEXSCO,RANGE,1,255)
VPUT (NNEXSCL) PROFILE
)END
./ ADD NAME=ONMPPRMG,SSI=01080031
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,9)
+
%Command ===>^ZCMD
+
+SYSOUT class ===>_Z+ Number of copies ===>_Z +
+(Note: Print data will be released to SYSOUT immediately.)
+Press%&END (END)+to cancel the print request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXSCL NNEXSCO)'
.CURSOR = NNEXSCL
&ZWINTTL = 'Print newsgroup listing'
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXSCL) PROFILE
&NNEXSCO = 1
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXSCL,NB,NAME)
IF (&NNEXSCO = &Z) &NNEXSCO = 1
VER(&NNEXSCO,NUM)
VER(&NNEXSCO,RANGE,1,255)
VPUT (NNEXSCL) PROFILE
)END
./ ADD NAME=ONMPPRNS,SSI=01070034
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY EXPAND(``) WINDOW(77,16)
+
%Command ===>^ZCMD
+
+SYSOUT class ===>_Z+ Number of copies ===>_Z +
+(Note: Print data will be released to SYSOUT immediately.)
+
+Page eject between articles? %===>_Z +
+Blank line after separator? %===>_Z +
+Separator line before each article (leave blank for none):
+>^Z +<
+From article number%===>_NNEXAN1 + (blank for first article in table)
+To article number%===>_NNEXAN2 + (blank for last article in table)
+Press%&END (END)+to cancel the print request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXSCL NNEXSCO NNEXSPA NNEXBLK NNEXSEP)'
.CURSOR = ZCMD
&ZWINTTL = 'Print text of articles in &NNGROUP'
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXSCL NNEXSPA NNEXBLK NNEXSEP) PROFILE
&NNEXSPA = TRANS(&NNEXSPA Y,YES N,NO ' ',NO)
&NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
&NNEXSCO = 1
&NNEXAN1 = &Z
&NNEXAN2 = &Z
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXSCL,NB,NAME)
&NNEXSPA = TRUNC(&NNEXSPA,1)
&NNEXBLK = TRUNC(&NNEXBLK,1)
VER(&NNEXSPA,NB,LIST,Y,N)
VER(&NNEXBLK,NB,LIST,Y,N)
IF (&NNEXSCO = &Z) &NNEXSCO = 1
VER(&NNEXSCO,NUM)
VER(&NNEXSCO,RANGE,1,255)
VER(&NNEXAN1,NUM)
VER(&NNEXAN2,NUM)
VPUT (NNEXSCL NNEXSPA NNEXBLK NNEXSEP) PROFILE
)END
./ ADD NAME=ONMPPRN1,SSI=01070041
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
)BODY WINDOW(77,9)
+
%Command ===>^ZCMD
+
+SYSOUT class ===>_Z+ Number of copies ===>_Z +
+(Note: Print data will be released to SYSOUT immediately.)
+Press%&END (END)+to cancel the print request.
)INIT
.HELP = TNNM
.ZVARS = '(NNEXSCL NNEXSCO)'
.CURSOR = NNEXSCL
&ZWINTTL = 'Print news article listing'
&END = PFK(END)
&ZCMD = &Z
VGET (NNEXSCL) PROFILE
&NNEXSCO = 1
)PROC
IF (&ZCMD ^= &Z) .MSG = ISPZ001
VER(&NNEXSCL,NB,NAME)
IF (&NNEXSCO = &Z) &NNEXSCO = 1
VER(&NNEXSCO,NUM)
VER(&NNEXSCO,RANGE,1,255)
VPUT (NNEXSCL) PROFILE
)END
./ ADD NAME=SASPANEL,SSI=01000042
(from Dale Ingold SNODDI@mvs.sas.com)
Here's the complete print panel, NNMQPRT. I've changed every non-
printable character to /xNN. (Would've used \, but that's my command
separator character.)
)PANEL KEYLIST(ISPSNAB,ISP)
)ATTR DEFAULT(/x01/x02/x03)
/x04 TYPE(TEXT) INTENS(LOW) SKIP(OFF) FORMAT(MIX) COLOR(BLUE)
/x05 TYPE(TEXT) INTENS(LOW) SKIP(OFF) FORMAT(MIX) COLOR(GREEN)
/x0A TYPE(OUTPUT) INTENS(LOW) FORMAT(MIX) CAPS(OFF) COLOR(WHITE)
/x09 TYPE(INPUT) INTENS(LOW) CAPS(OFF) JUST(LEFT) FORMAT(MIX)
PADC('_') COLOR(TURQ)
/x19 TYPE(INPUT) INTENS(LOW) CAPS(ON) JUST(LEFT) FORMAT(MIX)
PADC('_') COLOR(TURQ)
/x17 TYPE(TEXT) INTENS(LOW) SKIP(OFF) FORMAT(MIX) COLOR(TURQ)
)BODY WINDOW(60,22) CMD(ZCMD)
/x04 Set Print Options
/x05Command ===>/x09Z
/x04
/x05Article to be printed:
/x04
/x05Article nbr:/x0AZ /x17
/x05From . . . :/x0AZ /x17
/x05Date . . . :/x0AZ /x17
/x05Subject . :/x0AZ /x17
/x05Message ID :/x0AZ /x17
/x04
/x05Enter/verify the parameters below: /x05
/x05 /x05
/x05Destination /x09Z /x17
/x05Copies . . ./x09Z /x17/x05(Default is 1 copy) /x17
/x05Heading . ./x19Z /x17/x05(Yes to print heading) /x17
/x05Hold . . . ./x19Z /x17/x05(Yes to hold SYSOUT) /x17
/x05Form . . . ./x09Z /x17
/x05UCS . . . ./x09Z /x17
/x04
/x05Press ENTER to print or CANCEL to return.
)INIT
.ZVARS = '( ZCMD NNMPRTNM NNMPRTFM NNMPRTDT NNMPRTSJ NNMPRTID +
DEST CP HEAD HOLD FORM UCS )'
.HELP = TNNMQPRT
&ZCMD = ' '
&HEAD=TRANS (&HEAD
'Y','YES' 'Y','YO' 'N','NO' 'N','NES')
&HOLD=TRANS (&HOLD
'Y','YES' 'Y','YO' 'N','NO' 'N','NES')
)PROC
VER (&CP NUM)
&HEAD=TRANS (&HEAD
'YES','Y' 'YO','Y' 'NO','N' 'NES','N')
VER (&HEAD
LIST,Y,N )
&HOLD=TRANS (&HOLD
'YES','Y' 'YO','Y' 'NO','N' 'NES','N')
VER (&HOLD
LIST,Y,N )
)END
./ ADD NAME=TNNM
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
%
+NNMVS is an NNTP (network news transfer protocol)%news client+that runs on the
IBM mainframe using ISPF services. It retrieves news articles from an NNTP
%news server+executing on a host machine elsewhere on your network. You must
tell NNMVS where this news server is; it does not know otherwise.
+NNMVS remembers which articles you have read in a%"newsrc"+file, whose name
defaults to%&ZPREFIX..NEWSRC+. If you are a new user, you use the%L+or%blank+
+option to build your NEWSRC file with a list retrieved from the server. To
limit the list to your favorite newsgroups, you can register (subscribe to)
the ones you want while viewing the newsgroup list. Once you have used NNMVS
and built a NEWSRC file, you may wish to use a different entry option to reduce
startup time. You can avoid retrieving the whole list by using the%R+option to
view only%registered+(subscribed) newsgroups, or the%A+option to view%all+
newsgroups listed in your NEWSRC file. You can use the%N+option to get a list
of newsgroups added since the last time you retrieved the newsgroup list (i.e.
used%L+or%N+). The%G+option always goes directly to a specific newsgroup.
+Press%ENTER+to proceed with the tutorial, or enter a selection code:
%1+- Information on news servers
%2+- Information on NNTP, as described by RFC 977
)INIT
)PROC
&ZSEL = TRANS(&ZCMD,1,TNNMSERV,2,TNNMNNTP,*,?)
&ZCONT = TNNM001
)END
./ ADD NAME=TNNMB1,SSI=01020021
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
+When you select an article for viewing, you are placed in browse mode.
+You can use most NNMVS and ISPF BROWSE commands, plus the following commands:
%NEXT+ - proceed directly to the next article in the newsgroup
%NEXTSubj+ or%NS+- proceed directly to the next article on the same subject
%NEXTT+ or%NT+- proceed directly to the next article in the current table
%NEXTU+ or%NU+- proceed directly to the next unread article in the newsgroup
%PREV+ - proceed directly to the previous article in the newsgroup
%PREVSubj+ or%PS+- proceed directly to the previous article on the same subject
%PREVT+ or%PT+- proceed directly to the previous article in the current table
%PREVU+ or%PU+- proceed directly to the previous unread article in the group
%FIRSTSubj+or%FS+- proceed directly to first unread article on the same subject
%LASTSubj +or%LS+- proceed directly to last unread article on the same subject
%NEWSUBJ+ - proceed directly to first unread article on different subject
%SUBJECT+or%SUBJ+- display or change the current subject for subject searches
%UNREAD+ - stop reading this article and mark it unread
%EXTRACT+or%EXT+ - copy the article into a data set
%PRT+or%PRNT+ - print the article to SYSOUT
%ROT13+ - display "ROT13"-encoded text (toggle, do it again to reverse)
%FOLLOWUP+ - post a follow-up news article, news server permitting
%REPLY+ - send private mail to the originator of the news article
%HEADERs+ - customize article header line display (same as OPTIONS 1)
%(continued on next page)+
)INIT
IF (&TNNMTHR = NNMBROBF) &ZUP = ISR10000
ELSE &ZUP = TNNM001
&ZCONT = TNNMB2
)PROC
)END
./ ADD NAME=TNNMB2
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
%
+All the commands of ISPF BROWSE are supported under NNMVS browse, except for:
%HEX+
%BROWSE+
%SUBMIT+
%LOCATE .label+
%.<string>+(to assign a label)
%FIND P'generic-string'+
%DISPLAY CC/NOCC+
+For NEXTSUBJ, PREVSUBJ, FIRSTSUBJ and LASTSUBJ, the current subject is that
of the article being displayed. Alphabetic case is ignored, and subjects
with RE: and WAS: wrappers are taken into account.
+Note that NNTP protocol displays also use browse mode. When you are browsing
such output, commands relevant to article selection or sending are not
available. This means that EXTRACT and PRT are the only commands other
than browse and general NNMVS commands that you can use at such a time.
)INIT
)PROC
)END
./ ADD NAME=TNNMC,SSI=01000049
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
+The following commands are available from any of the display modes:
%OPTIONS+or%OPT+- set user options (e.g. for display of message headers)
%SAVE +- checkpoint%newsrc+(otherwise, will not be updated until exit)
%POST +- compose a news article for sending, news server permitting
%MAIL +- compose a mail message for sending to an individual user
%NNTP +- enter native NNTP protocol mode (for debugging only)
%DISCONNECT +- force disconnection from news server (reconnect automatic)
%QUIT +- leave NNMVS, saving changes in NEWSRC file
%CRASHNNMVS +- terminate NNMVS immediately, saving nothing
%DEBUG +- enable NNMVS debug mode (ddname NNDEBUG must be allocated)
%NODEBUG +- deactivate NNMVS debug mode
%TEST +- enter C/370 test mode (INSPECT)
+The following topics will be displayed next, or may be selected by number:
% 1 + - The Newsgroup Display (Available Selection Codes and Commands)
% 2 + - The Article Display (Available Selection Codes and Commands)
% 3 + - The Text Display (Available Commands)
% 4 + - Specifying User Options
)INIT
)PROC
&ZSEL = TRANS(&ZCMD 1,TNNMG 2,TNNMT 3,TNNMB1 4,TNNMOPT *,?)
&ZUP = TNNM
)END
./ ADD NAME=TNNMG,SSI=01020043
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
+In the%newsgroup+display, you may type a code in front of a newsgroup name:
%S+ - select: display articles, initially just those you haven't seen yet
%N+ - new: display unseen articles, removing seen ones from display
%A+ - all: display all articles, seen or unseen
%R+ - register: mark the newsgroup as one of your "subscribed" groups
%D+ - deregister: remove the newsgroup from your "subscribed" list
%M+ - mark read: tell the News Viewer you've seen everything in this group
%U+ - mark unread: tell the News Viewer you haven't seen anything in this group
%Q+ - query: display newsgroup status (for debugging only)
%&A+- &SELEC: display unseen articles, sorted by subject
%&B+- &AL: display all articles, sorted by subject
+You may type one of the following commands on the newsgroup command line:
%EXTRACT+or%EXT+ - copy the current list of newsgroups into a data set
%PRT+or%PRNT+ - print the current list of newsgroups to SYSOUT
%LOCATE+or%LOC+or%L+- position display at or near given newsgroup name
%FIND string option+- find NEXT, PREV, FIRST or LAST group containing string
%ONLY string+ - show only groups containing string (null string for all)
%REGISTER+or%REG+ - show registered (subscribed) newsgroups only
%ALL+ - show all newsgroups (registered and unregistered)
%ORDER Alpha/List+ - order groups alphabetically or by server's active file
)INIT
&A = '$'
&B = '@'
&SELEC = '$elect'
&AL = '@ll'
)PROC
&ZUP = TNNM001
)END
./ ADD NAME=TNNMNNTP
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
%
% ` ` NNTP (Network News Transfer Protocol) ` `
%
+RFC 977, "A Proposed Standard for the Stream-Based Transmission of News",
is the document that describes the Network News Transfer Protocol.
You may also wish to read:
RFC 1036, "Standard for Interchange of USENET Messages"
The%NNTP+option from the main NNMVS menu, or the%NNTP+command from any
NNMVS display command line, allows you to communicate directly with
the NNTP server using the protocol language defined in RFC 977, subject
to the support provided by the news server to which you are connected.
)INIT
)PROC
&ZUP = TNNM
)END
./ ADD NAME=TNNMOPT
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
%
% ` ` Options ` `
%
+The user options you set when you enter the OPTIONS command are remembered in
your ISPF profile, as is typical of ISPF dialogs. This is in contrast to
newsgroup and article status information, which is stored in your NEWSRC file
and not in your ISPF profile.
The first set of options specifies handling of the message headers that appear
in all news articles. You may specify whether you want all header lines to be
displayed, or just certain ones to be displayed, or certain ones NOT to be
displayed, or none to be displayed. The setting affects article extraction
into files as well as viewing.
+You may specify the frequency at which the News Viewer will update the screen
for long-running processes, such as retrieving articles from large newsgroups.
%(continued on next page)+
)INIT
)PROC
&ZUP = TNNM
&ZCONT = TNNMOPT2
)END
./ ADD NAME=TNNMOPT2
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
%
% ` ` Options - Screen Update Frequency ` `
%
+You may specify the frequency at which the News Viewer will update the screen
for long-running processes. These include:
fetching the list of all newsgroups
fetching the headers for unread articles in a newsgroup
fetching the current status of registered newsgroup
Specifying%ON+is the same as specifying a frequency of zero. The initial
default is%OFF,+but you may want to set it to%ON+or a number to experiment.
When you use the%L+or%blank+option to fetch the list of all newsgroups, since
the total number is not known, every newsgroup name will flash on the screen as
it is read if the Update option is not%OFF.+ For slow terminals, this can
greatly slow down the News Viewer; you should always specify%OFF+for slow
terminals if you intend to do this. While article titles are being fetched, if
Update is%OFF,+nothing is displayed until all titles are retrieved. Otherwise,
a bar graph showing the progress will be displayed at the indicated interval;
if Update is%ON+(the same as zero), the bar graph will be updated as every
title is read. An estimated time to completion will be displayed as well.
)INIT
)PROC
&ZUP = TNNM
)END
./ ADD NAME=TNNMSERV
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
%
% ` ` News Servers ` `
%
+Your NNMVS installation may already be configured to start you up with
a default news server host. If so, then you need do nothing special
to tell NNMVS to connect to it. Otherwise, you will need to provide the
name of the host running an NNTP news server.
+Ask your system administrator to tell you the hostname of the machine
where an available news server is running. You may need to ask the
administrator of that host to grant you permission to access the news server
from the MVS system where the News Viewer will be running as a client.
+If NNMVS does not recognize the hostname, you may specify an IP address
(four numbers separated by periods in the format nn.nn.nn.nn).
)INIT
)PROC
&ZUP = TNNM
)END
./ ADD NAME=TNNMT,SSI=01010038
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* SAS enhancements copyright (c) 1992 SAS Institute, Inc. /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
+In the%article+display, you may type these codes in front of an article number:
%S+ - select: browse the article text
%E+ - extract: copy the article into a data set
%P+ - print: print the article to SYSOUT
%M+ - mark read: tell the News Viewer you've already seen this article
%U+ - mark unread: tell the News Viewer you haven't seen this article
%F+ - followup: post a follow-up news article, news server permitting
%R+ - reply: send private mail to the originator of the news article
%C+ - cancel: send article cancel request to server (author must be you)
%Q+ - query: display article status (for debugging only)
+You may type one of the following commands on the article display command line:
%LOCATE+or%LOC+or%L+ - position display at or near given article number
%EXTRACT+or%EXT+ - copy titles or text of all articles into a data set
%PRT+or%PRNT+ - print titles or text of all articles to SYSOUT
%TITLES+or%TITLE+ - retrieve titles of all articles in table from the server
%QUERY+ - display newsgroup status (for debugging only)
%FIND string option+ - find NEXT, PREV, FIRST or LAST article with "string"
%ONLY string + - limit display to articles with "string" in the subject
%MARKALL+or%UNMARKALL+- mark all articles in this newsgroup read or unread
%SORT Subject/Number +- sort article display by subject or by article number
)INIT
)PROC
&ZUP = TNNM001
&TNNMTHR = &Z
)END
./ ADD NAME=TNNM001,SSI=01000018
)ATTR
/* /*
/* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992 /*
/* /*
/* This software is provided on an "AS IS" basis. All warranties, /*
/* including the implied warranties of merchantability and fitness, /*
/* are expressly denied. /*
/* /*
/* Provided this copyright notice is included, this software may /*
/* be freely distributed and not offered for sale. /*
/* /*
/* Changes or modifications may be made and used only by the maker /*
/* of same, and not further distributed. Such modifications should /*
/* be mailed to the author for consideration for addition to the /*
/* software and incorporation in subsequent releases. /*
/* /*
^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
# TYPE(TEXT) INTENS(LOW) COLOR(TURQ)
\ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
$ TYPE(TEXT) INTENS(LOW) COLOR(GREEN)
~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
)BODY EXPAND(``)
%TUTORIAL -`-`- MVS Network News Viewer -`-`- TUTORIAL
%SELECTION ===>_ZCMD +
%
+There are three kinds of displays created by the News Viewer:
% Newsgroups+ - which allows you to select newsgroups by name
% Articles + - which allows you to select articles by name
% Text + - which allows you to browse article text or NNTP output
+Additional commands are available specific to each of the above modes.
+The following topics will be displayed next, or may be selected by number:
% 1 + - Commands Available From All Displays
% 2 + - The Newsgroup Display (Available Selection Codes and Commands)
% 3 + - The Article Display (Available Selection Codes and Commands)
% 4 + - The Text Display (Available Commands)
% 5 + - Specifying User Options
)INIT
)PROC
&ZSEL = TRANS(&ZCMD 1,TNNMC 2,TNNMG 3,TNNMT 4,TNNMB1 5,TNNMOPT *,?)
&ZUP = TNNM
)END
./ ENDUP
?!